diff --git a/.circleci/config.yml b/.circleci/config.yml index 4c1db5c8..4c5acd08 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,11 +1,65 @@ -version: 3 +version: 2 + +defaults: &defaults + docker: + - image: circleci/node:10.9.0 + working_directory: ~/project + jobs: - build: - docker: - - image: circleci/node:10 - parallelism: 2 - working_directory: ~/react-navigation + install-dependencies: + <<: *defaults steps: - checkout - - run: yarn install --frozen-lockfile - - run: ./scripts/test.sh + - attach_workspace: + at: ~/project + - restore_cache: + keys: + - v1-dependencies-{{ checksum "package.json" }} + - v1-dependencies- + - restore_cache: + keys: + - v1-dependencies-example-{{ checksum "example/package.json" }} + - v1-dependencies-example- + - run: | + yarn install --frozen-lockfile + yarn install --frozen-lockfile --cwd example + - save_cache: + key: v1-dependencies-{{ checksum "package.json" }} + paths: node_modules + - save_cache: + key: v1-dependencies-example-{{ checksum "example/package.json" }} + paths: example/node_modules + - persist_to_workspace: + root: . + paths: . + lint-and-typecheck: + <<: *defaults + steps: + - attach_workspace: + at: ~/project + - run: | + yarn lint + yarn typescript + unit-tests: + <<: *defaults + steps: + - attach_workspace: + at: ~/project + - run: | + yarn test --coverage + yarn codecov + - store_artifacts: + path: coverage + destination: coverage + +workflows: + version: 2 + build-and-test: + jobs: + - install-dependencies + - lint-and-typecheck: + requires: + - install-dependencies + - unit-tests: + requires: + - install-dependencies diff --git a/.eslintignore b/.eslintignore index 44cf8287..7f0ae633 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,8 +1,6 @@ -coverage -flow -node_modules -lib* -build - -## Temporary -examples +coverage/ +flow/ +node_modules/ +lib/ +build/ +typescript/ diff --git a/.eslintrc b/.eslintrc index 8e10f4f8..4dcef5e3 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,52 +1,21 @@ { - "extends": [ - "plugin:react/recommended", - "plugin:import/errors", - "plugin:import/warnings", - "prettier", - "prettier/react" - ], - "parser": "babel-eslint", - "plugins": ["react", "prettier"], + "extends": "eslint-config-satya164", + + "plugins": ["react-native-globals"], + + "settings": { + "react": { + "version": "detect" + }, + }, + "env": { - "jasmine": true + "es6": true, + "react-native-globals/all": true, }, + "rules": { - "prettier/prettier": [ - "error", - { - "trailingComma": "es5", - "singleQuote": true - } - ], - - "no-underscore-dangle": "off", - "no-use-before-define": "off", - "no-unused-expressions": "off", - "new-cap": "off", - "no-plusplus": "off", - "no-class-assign": "off", - "no-duplicate-imports": "off", - "import/extensions": "off", - "import/no-extraneous-dependencies": "off", "import/no-unresolved": "off", - - "react/jsx-filename-extension": ["off", { "extensions": [".js", ".jsx"] }], - - "react/sort-comp": "off", - "react/prefer-stateless-function": "off", - "react/no-deprecated": "off", - - "react/forbid-prop-types": "warn", - "react/prop-types": "off", - "react/require-default-props": "off", - "react/no-unused-prop-types": "off" - }, - "parserOptions": { - "ecmaVersion": 6, - "sourceType": "module", - "ecmaFeatures": { - "modules": true - } + "react/sort-comp": "off" } } diff --git a/.release-it.json b/.release-it.json index 6893ef15..7840e078 100644 --- a/.release-it.json +++ b/.release-it.json @@ -1,8 +1,5 @@ { - "increment": "conventional:angular", - "changelogCommand": "conventional-changelog -p angular | tail -n +3", - "safeBump": false, - "src": { + "git": { "commitMessage": "chore: release %s", "tagName": "v%s" }, @@ -11,5 +8,10 @@ }, "github": { "release": true + }, + "plugins": { + "@release-it/conventional-changelog": { + "preset": "angular" + } } } diff --git a/LICENSE b/LICENSE index 063ab66b..001d6a9b 100644 --- a/LICENSE +++ b/LICENSE @@ -1,26 +1,21 @@ -BSD License +MIT License -For React Navigation software +Copyright (c) 2017 React Native Community -Copyright (c) 2016-present, React Navigation Contributors. All rights reserved. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/assetsTransformer.js b/assetsTransformer.js index 4af49e37..c2fec9ac 100644 --- a/assetsTransformer.js +++ b/assetsTransformer.js @@ -1,3 +1,4 @@ +/* eslint-disable import/no-commonjs */ /** * This file is needed to hijack asset imports so that test files don't attempt * to import them as JavaScript modules. @@ -6,7 +7,7 @@ const path = require('path'); module.exports = { - process(src, filename, config, options) { + process(src, filename) { return 'module.exports = ' + JSON.stringify(path.basename(filename)) + ';'; }, }; diff --git a/babel.config.js b/babel.config.js index f842b77f..547fee30 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,3 +1,5 @@ +/* eslint-disable import/no-commonjs */ + module.exports = { presets: ['module:metro-react-native-babel-preset'], }; diff --git a/commitlint.config.js b/commitlint.config.js new file mode 100644 index 00000000..cc8383f7 --- /dev/null +++ b/commitlint.config.js @@ -0,0 +1,5 @@ +/* eslint-disable import/no-commonjs */ + +module.exports = { + extends: ['@commitlint/config-conventional'], +}; diff --git a/example/.babelrc b/example/.babelrc new file mode 100644 index 00000000..439ba33e --- /dev/null +++ b/example/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["expo"] +} diff --git a/examples/NavigationPlayground/.buckconfig b/example/.buckconfig similarity index 100% rename from examples/NavigationPlayground/.buckconfig rename to example/.buckconfig diff --git a/example/.eslintrc b/example/.eslintrc new file mode 100644 index 00000000..1b540fa1 --- /dev/null +++ b/example/.eslintrc @@ -0,0 +1,18 @@ +{ + 'extends': '../.eslintrc', + + 'settings': + { + 'import/core-modules': + [ + 'expo-asset', + 'react-navigation-stack', + 'react-native-gesture-handler', + 'react-native-reanimated', + ], + }, + + "rules": { + "react-native/no-inline-styles": "off" + } +} diff --git a/examples/NavigationPlayground/.watchmanconfig b/example/.watchmanconfig similarity index 100% rename from examples/NavigationPlayground/.watchmanconfig rename to example/.watchmanconfig diff --git a/examples/NavigationPlayground/App.tsx b/example/App.tsx similarity index 98% rename from examples/NavigationPlayground/App.tsx rename to example/App.tsx index b29440da..f17f0bea 100644 --- a/examples/NavigationPlayground/App.tsx +++ b/example/App.tsx @@ -19,9 +19,9 @@ import { ThemeContext, Themed, createAppContainer, - createStackNavigator, SafeAreaView, } from 'react-navigation'; +import { createStackNavigator } from 'react-navigation-stack'; import { MaterialCommunityIcons } from '@expo/vector-icons'; import CustomTabs from './src/CustomTabs'; import CustomTabUI from './src/CustomTabUI'; @@ -428,13 +428,6 @@ const styles = StyleSheet.create({ color: '#999', fontSize: 13, }, - image: { - alignSelf: 'center', - height: 120, - marginBottom: 20, - resizeMode: 'contain', - width: 120, - }, item: { borderBottomWidth: StyleSheet.hairlineWidth, paddingHorizontal: 16, diff --git a/example/app.json b/example/app.json new file mode 100644 index 00000000..dadea853 --- /dev/null +++ b/example/app.json @@ -0,0 +1,14 @@ +{ + "expo": { + "name": "React Navigation Stack Example", + "description": "Demonstrates the various capabilities of react-navigation-stack", + "slug": "react-navigation-stack-demo", + "sdkVersion": "33.0.0", + "version": "1.0.0", + "primaryColor": "#2196f3", + "packagerOpts": { + "config": "./metro.config.js", + "projectRoots": "" + } + } +} diff --git a/example/metro.config.js b/example/metro.config.js new file mode 100644 index 00000000..00afc215 --- /dev/null +++ b/example/metro.config.js @@ -0,0 +1,35 @@ +/* eslint-disable import/no-extraneous-dependencies, import/no-commonjs */ + +const path = require('path'); +const blacklist = require('metro-config/src/defaults/blacklist'); +const project = require('../package.json'); +const escape = require('escape-string-regexp'); + +const projectDependencies = Object.keys({ + ...project.dependencies, + ...project.peerDependencies, +}); + +module.exports = { + projectRoot: __dirname, + watchFolders: [path.resolve(__dirname, '..')], + + resolver: { + blacklistRE: blacklist([ + new RegExp( + `^${escape( + path.resolve(__dirname, 'node_modules', project.name) + )}\\/.*$` + ), + new RegExp( + `^${escape(path.resolve(__dirname, '..', 'node_modules'))}\\/.*$` + ), + ]), + + providesModuleNodeModules: [ + '@expo/vector-icons', + '@babel/runtime', + ...projectDependencies, + ], + }, +}; diff --git a/example/package.json b/example/package.json new file mode 100644 index 00000000..bf148a1b --- /dev/null +++ b/example/package.json @@ -0,0 +1,37 @@ +{ + "name": "playground", + "version": "0.0.1", + "private": true, + "main": "node_modules/expo/AppEntry.js", + "scripts": { + "start": "expo start", + "android": "expo start --android", + "ios": "expo start --ios" + }, + "dependencies": { + "@expo/vector-icons": "^10.0.0", + "@react-native-community/masked-view": "^0.1.1", + "@react-navigation/core": "^3.5.0", + "@react-navigation/native": "^3.6.2", + "expo": "^33.0.7", + "expo-asset": "^5.0.1", + "expo-blur": "~5.0.1", + "expo-constants": "~5.0.1", + "hoist-non-react-statics": "^3.3.0", + "react": "16.8.3", + "react-native": "https://github.com/expo/react-native/archive/sdk-33.0.0.tar.gz", + "react-native-iphone-x-helper": "^1.2.1", + "react-native-paper": "^2.15.2", + "react-navigation-drawer": "^2.0.1", + "react-navigation-header-buttons": "^3.0.2", + "react-navigation-stack": "^1.5.1", + "react-navigation-tabs": "^1.2.0" + }, + "devDependencies": { + "babel-plugin-module-resolver": "^3.2.0" + }, + "resolutions": { + "react-native-safe-area-view": "0.14.6", + "react-native-screens": "1.0.0-alpha.23" + } +} diff --git a/examples/NavigationPlayground/src/CustomTabUI.tsx b/example/src/CustomTabUI.tsx similarity index 96% rename from examples/NavigationPlayground/src/CustomTabUI.tsx rename to example/src/CustomTabUI.tsx index 83a76fdd..2254c4fc 100644 --- a/examples/NavigationPlayground/src/CustomTabUI.tsx +++ b/example/src/CustomTabUI.tsx @@ -8,16 +8,18 @@ import { Text, View, } from 'react-native'; -import Ionicons from 'react-native-vector-icons/Ionicons'; +import { Ionicons } from '@expo/vector-icons'; import { - MaterialTopTabBar, Themed, - createMaterialTopTabNavigator, ThemeContext, NavigationScreenProp, NavigationState, SafeAreaView, } from 'react-navigation'; +import { + createMaterialTopTabNavigator, + MaterialTopTabBar, +} from 'react-navigation-tabs'; import { Button } from './commonComponents/ButtonWithMargin'; interface Props { @@ -108,11 +110,7 @@ class MaterialTopTabBarWrapper extends React.Component { } class FeaturedScreen extends React.Component { - static navigationOptions = ({ - navigation, - }: { - navigation: NavigationScreenProp; - }) => ({ + static navigationOptions = { tabBarLabel: 'Featured', tabBarIcon: ({ tintColor, @@ -129,7 +127,8 @@ class FeaturedScreen extends React.Component { style={{ color: tintColor }} /> ), - }); + }; + render() { const { navigation } = this.props; return ( diff --git a/examples/NavigationPlayground/src/CustomTabs.tsx b/example/src/CustomTabs.tsx similarity index 97% rename from examples/NavigationPlayground/src/CustomTabs.tsx rename to example/src/CustomTabs.tsx index 21f08f05..92221f12 100644 --- a/examples/NavigationPlayground/src/CustomTabs.tsx +++ b/example/src/CustomTabs.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { ScrollView, StatusBar, StyleSheet, Text } from 'react-native'; +import { ScrollView, StyleSheet } from 'react-native'; import { BorderlessButton } from 'react-native-gesture-handler'; import { createNavigator, diff --git a/examples/NavigationPlayground/src/Drawer.tsx b/example/src/Drawer.tsx similarity index 80% rename from examples/NavigationPlayground/src/Drawer.tsx rename to example/src/Drawer.tsx index 946442bb..aedc1377 100644 --- a/examples/NavigationPlayground/src/Drawer.tsx +++ b/example/src/Drawer.tsx @@ -1,13 +1,14 @@ import React from 'react'; import { ScrollView, StyleProp, TextStyle } from 'react-native'; -import MaterialIcons from 'react-native-vector-icons/MaterialIcons'; +import { MaterialIcons } from '@expo/vector-icons'; import { - createDrawerNavigator, - createStackNavigator, Themed, SafeAreaView, + NavigationScreenProp, + NavigationState, } from 'react-navigation'; -import { NavigationScreenProp, NavigationState } from 'react-navigation'; +import { createStackNavigator } from 'react-navigation-stack'; +import { createDrawerNavigator } from 'react-navigation-drawer'; import { Button } from './commonComponents/ButtonWithMargin'; import SampleText from './SampleText'; @@ -36,7 +37,7 @@ const InboxScreen = ({ navigation, }: { navigation: NavigationScreenProp; -}) => ; +}) => ; InboxScreen.navigationOptions = { headerTitle: 'Inbox', }; @@ -45,13 +46,13 @@ const EmailScreen = ({ navigation, }: { navigation: NavigationScreenProp; -}) => ; +}) => ; const DraftsScreen = ({ navigation, }: { navigation: NavigationScreenProp; -}) => ; +}) => ; DraftsScreen.navigationOptions = { headerTitle: 'Drafts', }; @@ -63,7 +64,7 @@ const InboxStack = createStackNavigator( }, { navigationOptions: { - drawerIcon: ({ tintColor }) => ( + drawerIcon: ({ tintColor }: { tintColor: string }) => ( ( + drawerIcon: ({ tintColor }: { tintColor: string }) => ( ; -}) => ; +}) => ; MyHeaderTestScreen.navigationOptions = ({ navigation, }: { diff --git a/examples/NavigationPlayground/src/SampleText.tsx b/example/src/SampleText.tsx similarity index 88% rename from examples/NavigationPlayground/src/SampleText.tsx rename to example/src/SampleText.tsx index 1b4984b4..bbddb3f6 100644 --- a/examples/NavigationPlayground/src/SampleText.tsx +++ b/example/src/SampleText.tsx @@ -1,5 +1,5 @@ import React, { ReactNode } from 'react'; -import { StyleSheet, Text } from 'react-native'; +import { StyleSheet } from 'react-native'; import { Themed } from 'react-navigation'; /** diff --git a/examples/NavigationPlayground/src/SimpleStack.tsx b/example/src/SimpleStack.tsx similarity index 98% rename from examples/NavigationPlayground/src/SimpleStack.tsx rename to example/src/SimpleStack.tsx index 13f9178b..aebbace8 100644 --- a/examples/NavigationPlayground/src/SimpleStack.tsx +++ b/example/src/SimpleStack.tsx @@ -2,7 +2,6 @@ import * as React from 'react'; import { - createStackNavigator, NavigationActions, NavigationEventPayload, NavigationEventSubscription, @@ -14,6 +13,7 @@ import { Themed, withNavigation, } from 'react-navigation'; +import { createStackNavigator } from 'react-navigation-stack'; import { Button } from './commonComponents/ButtonWithMargin'; import { HeaderButtons } from './commonComponents/HeaderButtons'; import SampleText from './SampleText'; @@ -148,7 +148,7 @@ interface MyPhotosScreenProps { } class MyPhotosScreen extends React.Component { static navigationOptions = { - headerLeft: , + headerLeft: () => , title: 'Photos', }; s0: NavigationEventSubscription | null = null; diff --git a/examples/NavigationPlayground/src/SimpleTabs.tsx b/example/src/SimpleTabs.tsx similarity index 93% rename from examples/NavigationPlayground/src/SimpleTabs.tsx rename to example/src/SimpleTabs.tsx index b5fb02e4..fe4d4f76 100644 --- a/examples/NavigationPlayground/src/SimpleTabs.tsx +++ b/example/src/SimpleTabs.tsx @@ -1,15 +1,16 @@ import React from 'react'; -import Ionicons from 'react-native-vector-icons/Ionicons'; +import { Ionicons } from '@expo/vector-icons'; import { - createBottomTabNavigator, FlatList, NavigationEventSubscription, NavigationScreenProp, SafeAreaView, Themed, ScrollView, + NavigationEventPayload, + NavigationState, } from 'react-navigation'; -import { NavigationEventPayload, NavigationState } from 'react-navigation'; +import { createBottomTabNavigator } from 'react-navigation-tabs'; import { Button } from './commonComponents/ButtonWithMargin'; import SampleText from './SampleText'; @@ -37,7 +38,10 @@ const MyNavScreen = ({ />