chore: setup monorepo with yarn workspaces (#38)

This commit is contained in:
Satyajit Sahoo
2019-08-02 00:40:57 +02:00
committed by Michał Osadnik
parent 0d68f1ed59
commit ce7d163073
62 changed files with 7933 additions and 3020 deletions

View File

@@ -1,16 +0,0 @@
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage",
"corejs": 3
}
],
"@babel/preset-react",
"@babel/preset-typescript"
],
"plugins": [
"@babel/plugin-proposal-class-properties"
]
}

View File

@@ -2,4 +2,5 @@ node_modules/
coverage/
dist/
lib/
types/
web-build/
web-report/

View File

@@ -1,11 +0,0 @@
{
extends: 'satya164',
settings: {
react: {
version: '16'
}
},
env: {
browser: true
}
}

8
.eslintrc.json Normal file
View File

@@ -0,0 +1,8 @@
{
"extends": "satya164",
"settings": {
"react": { "version": "16" },
"import/core-modules": ["@navigation-ex/core", "@navigation-ex/routers"]
},
"env": { "browser": true }
}

15
.gitignore vendored
View File

@@ -2,9 +2,22 @@
.cache
.vscode
.idea
.expo
/coverage/
/types/
/lib/
/dist/
/node_modules/
node_modules/
web-build/
web-report/
npm-debug.*
*.jks
*.p8
*.p12
*.key
*.mobileprovision
*.orig.*

1
.watchmanconfig Normal file
View File

@@ -0,0 +1 @@
{}

17
babel.config.js Normal file
View File

@@ -0,0 +1,17 @@
/* eslint-disable import/no-commonjs */
/* eslint-env node */
module.exports = {
presets: [
[
'@babel/preset-env',
{
useBuiltIns: 'usage',
corejs: 3,
},
],
'@babel/preset-react',
'@babel/preset-typescript',
],
plugins: ['@babel/plugin-proposal-class-properties'],
};

View File

@@ -1,34 +0,0 @@
<style type="text/css">
html {
box-sizing: border-box;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
*:focus {
outline: none;
}
*:focus-visible {
outline: auto;
}
html,
body {
height: 100%;
width: 100%;
}
body {
font-family: 'Source Sans Pro', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 14px;
line-height: 1.42857143;
background-color: #E2E1E0;
}
</style>
<div id="root"></div>
<script src="./index.tsx"></script>

View File

@@ -1,16 +1,20 @@
{
"name": "navigation-ex",
"private": true,
"version": "0.0.0",
"description": "Rethinking navigation",
"keywords": [],
"types": "types/index.d.ts",
"main": "lib/index.js",
"files": [
"lib/",
"types/",
"index.d.ts"
],
"private": true,
"workspaces": {
"packages": [
"packages/*"
],
"nohoist": [
"**/expo",
"**/expo/**",
"**/react-native",
"**/react-native/**"
]
},
"publishConfig": {
"registry": "https://registry.npmjs.org/"
},
"license": "MIT",
"repository": {
"type": "git",
@@ -21,48 +25,25 @@
"lint": "eslint --ext '.js,.ts,.tsx' .",
"typescript": "tsc --noEmit",
"test": "jest",
"prebuild": "del lib/ types/",
"babel": "babel src --out-dir lib --ignore '**/__tests__/**' --source-maps",
"declarations": "tsc --declaration --emitDeclarationOnly --outDir types",
"build": "yarn babel && yarn declarations",
"example": "parcel example/index.html",
"prepare": "yarn build",
"release": "release-it"
},
"publishConfig": {
"registry": "https://registry.npmjs.org/"
},
"dependencies": {
"core-js": "^3.1.3",
"shortid": "^2.2.14"
"example": "yarn --cwd packages/example"
},
"devDependencies": {
"@babel/cli": "^7.4.4",
"@babel/core": "^7.4.5",
"@babel/plugin-proposal-class-properties": "^7.5.0",
"@babel/preset-env": "^7.4.5",
"@babel/plugin-proposal-class-properties": "^7.5.5",
"@babel/preset-env": "^7.5.5",
"@babel/preset-react": "^7.0.0",
"@babel/preset-typescript": "^7.3.3",
"@babel/runtime": "^7.5.5",
"@commitlint/config-conventional": "^8.0.0",
"@release-it/conventional-changelog": "^1.1.0",
"@types/jest": "^24.0.13",
"@types/react": "^16.8.19",
"@types/react-dom": "^16.8.4",
"@types/shortid": "^0.0.29",
"codecov": "^3.5.0",
"commitlint": "^8.0.0",
"core-js": "^3.1.4",
"del-cli": "^2.0.0",
"eslint": "^5.16.0",
"eslint-config-satya164": "^2.4.1",
"husky": "^2.4.0",
"jest": "^24.8.0",
"parcel": "^1.12.3",
"prettier": "^1.18.2",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"react-native-testing-library": "^1.9.1",
"react-test-renderer": "^16.8.6",
"release-it": "^12.3.0",
"typescript": "^3.5.1"
},
"husky": {
@@ -73,14 +54,12 @@
},
"jest": {
"testEnvironment": "node",
"modulePathIgnorePatterns": [
"<rootDir>/types/",
"<rootDir>/lib/"
],
"testRegex": "/__tests__/.*\\.(test|spec)\\.(js|tsx?)$",
"transform": {
"^.+\\.(js|ts|tsx)$": "babel-jest"
},
"setupFiles": ["<rootDir>/jest/setup.js"]
"setupFiles": [
"<rootDir>/jest/setup.js"
]
}
}

View File

@@ -0,0 +1,20 @@
{
"name": "@navigation-ex/core",
"version": "0.0.1",
"main": "src/index",
"license": "MIT",
"dependencies": {
"shortid": "^2.2.14"
},
"devDependencies": {
"@babel/core": "^7.4.5",
"react": "^16.8.3",
"react-native-testing-library": "^1.9.1",
"react-test-renderer": "^16.8.3",
"@types/react": "^16.8.19",
"@types/shortid": "^0.0.29"
},
"peerDependencies": {
"react": "^16.8.3"
}
}

View File

@@ -1,7 +1,7 @@
import * as React from 'react';
import useNavigation from './useNavigation';
type EffectCallback = (() => undefined) | (() => () => void);
type EffectCallback = (() => void) | (() => () => void);
/**
* Hook to an effect in a focused screen, similar to `React.useEffect`.
@@ -15,7 +15,7 @@ export default function useFocusEffect(callback: EffectCallback) {
React.useEffect(() => {
let isFocused = false;
let cleanup: (() => void) | undefined;
let cleanup: (() => void) | void;
// We need to run the effect on intial render/dep changes if the screen is focused
if (navigation.isFocused()) {

View File

@@ -0,0 +1,4 @@
{
"f9155ac790fd02fadcdeca367b02581c04a353aa6d5aa84409a59f6804c87acd": true,
"89ed26367cdb9b771858e026f2eb95bfdb90e5ae943e716575327ec325f39c44": true
}

1
packages/example/App.tsx Normal file
View File

@@ -0,0 +1 @@
export { default } from './src/index';

30
packages/example/app.json Normal file
View File

@@ -0,0 +1,30 @@
{
"expo": {
"name": "@navigation-ex/example",
"slug": "navigation-ex-example",
"privacy": "public",
"sdkVersion": "34.0.0",
"platforms": [
"ios",
"android",
"web"
],
"version": "1.0.0",
"orientation": "portrait",
"icon": "./assets/icon.png",
"splash": {
"image": "./assets/splash.png",
"resizeMode": "contain",
"backgroundColor": "#ffffff"
},
"updates": {
"fallbackToCacheTimeout": 0
},
"assetBundlePatterns": [
"**/*"
],
"ios": {
"supportsTablet": true
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

@@ -0,0 +1,9 @@
/* eslint-disable import/no-commonjs */
/* eslint-env node */
module.exports = function(api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
};
};

View File

@@ -0,0 +1,46 @@
/* eslint-disable import/no-commonjs, import/no-extraneous-dependencies */
/* eslint-env node */
const path = require('path');
const fs = require('fs');
const escape = require('escape-string-regexp');
const blacklist = require('metro-config/src/defaults/blacklist');
module.exports = {
projectRoot: __dirname,
watchFolders: [path.resolve(__dirname, '..', '..')],
resolver: {
blacklistRE: blacklist(
[
...fs
.readdirSync(path.resolve(__dirname, '..'))
.filter(d => d !== 'example'),
'..',
].map(
it =>
new RegExp(
`^${escape(
path.resolve(__dirname, '..', it, 'node_modules')
)}\\/.*$`
)
)
),
providesModuleNodeModules: [
'@babel/runtime',
'react',
'react-native',
'shortid',
],
},
transformer: {
getTransformOptions: async () => ({
transform: {
experimentalImportSupport: false,
inlineRequires: true,
},
}),
},
};

View File

@@ -0,0 +1,41 @@
{
"name": "@navigation-ex/example",
"version": "0.0.0",
"private": true,
"workspaces": {
"nohoist": [
"*",
"*/**"
]
},
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web",
"eject": "expo eject"
},
"dependencies": {
"expo": "^34.0.1",
"react": "16.8.3",
"react-dom": "^16.8.3",
"react-native": "https://github.com/expo/react-native/archive/sdk-34.0.0.tar.gz",
"react-native-paper": "3.0.0-alpha.3",
"react-native-web": "^0.11.4",
"scheduler": "^0.14.0",
"shortid": "^2.2.14"
},
"devDependencies": {
"@babel/core": "^7.5.5",
"@expo/webpack-config": "^0.7.0",
"@types/react": "^16.8.23",
"@types/react-native": "^0.57.65",
"babel-preset-expo": "^6.0.0",
"expo-cli": "^3.0.6"
},
"resolutions": {
"react": "16.8.3",
"react-dom": "^16.8.3"
}
}

View File

@@ -0,0 +1,105 @@
/* eslint-disable react-native/no-inline-styles */
import * as React from 'react';
import { Text, View } from 'react-native';
import {
useNavigationBuilder,
NavigationProp,
ParamListBase,
createNavigator,
} from '@navigation-ex/core';
import {
StackRouter,
StackRouterOptions,
StackNavigationState,
} from '@navigation-ex/routers';
type Props = StackRouterOptions & {
children: React.ReactNode;
};
export type StackNavigationOptions = {
/**
* Title text for the screen.
*/
title?: string;
};
export type StackNavigationProp<
ParamList extends ParamListBase,
RouteName extends keyof ParamList = string
> = NavigationProp<
ParamList,
RouteName,
StackNavigationState,
StackNavigationOptions
> & {
/**
* Push a new screen onto the stack.
*
* @param name Name of the route for the tab.
* @param [params] Params object for the route.
*/
push<RouteName extends keyof ParamList>(
...args: ParamList[RouteName] extends void
? [RouteName]
: [RouteName, ParamList[RouteName]]
): void;
/**
* Pop a screen from the stack.
*/
pop(count?: number): void;
/**
* Pop to the first route in the stack, dismissing all other screens.
*/
popToTop(): void;
};
export function StackNavigator(props: Props) {
const { state, descriptors } = useNavigationBuilder<
StackNavigationState,
StackNavigationOptions,
StackRouterOptions
>(StackRouter, props);
return (
<View>
{state.routes.map((route, i) => (
<View
key={route.key}
style={{
position: 'absolute',
margin: 20,
left: i * 20,
top: i * 20,
padding: 10,
height: 480,
width: 320,
backgroundColor: 'white',
borderRadius: 3,
}}
>
{descriptors[route.key].render()}
</View>
))}
<View
style={{
position: 'absolute',
left: 40,
width: 120,
padding: 10,
backgroundColor: 'tomato',
borderRadius: 3,
}}
>
<Text>{descriptors[state.routes[state.index].key].options.title}</Text>
</View>
</View>
);
}
export default createNavigator<StackNavigationOptions, typeof StackNavigator>(
StackNavigator
);

View File

@@ -0,0 +1,78 @@
/* eslint-disable react-native/no-inline-styles */
import * as React from 'react';
import { View } from 'react-native';
import {
useNavigationBuilder,
NavigationProp,
ParamListBase,
createNavigator,
} from '@navigation-ex/core';
import {
TabRouter,
TabRouterOptions,
TabNavigationState,
} from '@navigation-ex/routers';
type Props = TabRouterOptions & {
children: React.ReactNode;
};
export type TabNavigationOptions = {
/**
* Title text for the screen.
*/
title?: string;
};
export type TabNavigationProp<
ParamList extends ParamListBase,
RouteName extends keyof ParamList = string
> = NavigationProp<
ParamList,
RouteName,
TabNavigationState,
TabNavigationOptions
> & {
/**
* Jump to an existing tab.
*
* @param name Name of the route for the tab.
* @param [params] Params object for the route.
*/
jumpTo<RouteName extends Extract<keyof ParamList, string>>(
...args: ParamList[RouteName] extends void
? [RouteName]
: [RouteName, ParamList[RouteName]]
): void;
};
export function TabNavigator(props: Props) {
const { state, descriptors } = useNavigationBuilder<
TabNavigationState,
TabNavigationOptions,
TabRouterOptions
>(TabRouter, props);
return (
<View style={{ display: 'flex', flexDirection: 'row', height: '100%' }}>
{state.routes.map((route, i, self) => (
<View
key={route.key}
style={{
width: `${100 / self.length}%`,
padding: 10,
borderRadius: 3,
backgroundColor: i === state.index ? 'tomato' : 'white',
}}
>
{descriptors[route.key].render()}
</View>
))}
</View>
);
}
export default createNavigator<TabNavigationOptions, typeof TabNavigator>(
TabNavigator
);

View File

@@ -1,5 +1,13 @@
import * as React from 'react';
import { render } from 'react-dom';
import {
View,
Text,
Platform,
AsyncStorage,
YellowBox,
StyleSheet,
} from 'react-native';
import { Button } from 'react-native-paper';
import {
NavigationContainer,
CompositeNavigationProp,
@@ -7,7 +15,7 @@ import {
RouteProp,
InitialState,
useFocusEffect,
} from '../src';
} from '@navigation-ex/core';
import createStackNavigator, { StackNavigationProp } from './StackNavigator';
import createTabNavigator, { TabNavigationProp } from './TabNavigator';
@@ -22,6 +30,8 @@ type TabParamList = {
fifth: undefined;
};
YellowBox.ignoreWarnings(['Require cycle:', 'Warning: Async Storage']);
const Stack = createStackNavigator<StackParamList>();
const Tab = createTabNavigator<TabParamList>();
@@ -37,35 +47,32 @@ const First = ({
route: RouteProp<StackParamList, 'first'>;
}) => {
const updateTitle = React.useCallback(() => {
if (Platform.OS !== 'web') {
return;
}
document.title = `${route.name} (${route.params.author})`;
return () => (document.title = '');
return () => {
document.title = '';
};
}, [route.name, route.params.author]);
useFocusEffect(updateTitle);
return (
<div>
<h1>First, {route.params.author}</h1>
<button type="button" onClick={() => navigation.push('second')}>
Push second
</button>
<button type="button" onClick={() => navigation.push('third')}>
Push third
</button>
<button type="button" onClick={() => navigation.navigate('fourth')}>
<View>
<Text style={styles.title}>First, {route.params.author}</Text>
<Button onPress={() => navigation.push('second')}>Push second</Button>
<Button onPress={() => navigation.push('third')}>Push third</Button>
<Button onPress={() => navigation.navigate('fourth')}>
Navigate to fourth
</button>
<button
type="button"
onClick={() => navigation.navigate('first', { author: 'John' })}
>
</Button>
<Button onPress={() => navigation.navigate('first', { author: 'John' })}>
Navigate with params
</button>
<button type="button" onClick={() => navigation.pop()}>
Pop
</button>
</div>
</Button>
<Button onPress={() => navigation.pop()}>Pop</Button>
</View>
);
};
@@ -90,18 +97,13 @@ const Second = ({
});
return (
<div>
<h1>Second</h1>
<button
type="button"
onClick={() => navigation.push('first', { author: 'Joel' })}
>
<View>
<Text style={styles.title}>Second</Text>
<Button onPress={() => navigation.push('first', { author: 'Joel' })}>
Push first
</button>
<button type="button" onClick={() => navigation.pop()}>
Pop
</button>
</div>
</Button>
<Button onPress={() => navigation.pop()}>Pop</Button>
</View>
);
};
@@ -113,21 +115,14 @@ const Fourth = ({
StackNavigationProp<StackParamList>
>;
}) => (
<div>
<h1>Fourth</h1>
<button type="button" onClick={() => navigation.jumpTo('fifth')}>
Jump to fifth
</button>
<button
type="button"
onClick={() => navigation.push('first', { author: 'Jake' })}
>
<View>
<Text style={styles.title}>Fourth</Text>
<Button onPress={() => navigation.jumpTo('fifth')}>Jump to fifth</Button>
<Button onPress={() => navigation.push('first', { author: 'Jake' })}>
Push first
</button>
<button type="button" onClick={() => navigation.goBack()}>
Go back
</button>
</div>
</Button>
<Button onPress={() => navigation.goBack()}>Go back</Button>
</View>
);
const Fifth = ({
@@ -138,36 +133,48 @@ const Fifth = ({
StackNavigationProp<StackParamList>
>;
}) => (
<div>
<h1>Fifth</h1>
<button type="button" onClick={() => navigation.jumpTo('fourth')}>
Jump to fourth
</button>
<button type="button" onClick={() => navigation.push('second')}>
Push second
</button>
<button type="button" onClick={() => navigation.pop()}>
Pop
</button>
</div>
<View>
<Text style={styles.title}>Fifth</Text>
<Button onPress={() => navigation.jumpTo('fourth')}>Jump to fourth</Button>
<Button onPress={() => navigation.push('second')}>Push second</Button>
<Button onPress={() => navigation.pop()}>Pop</Button>
</View>
);
const PERSISTENCE_KEY = 'NAVIGATION_STATE';
let initialState: InitialState | undefined;
export default function App() {
const [isReady, setIsReady] = React.useState(false);
const [initialState, setInitialState] = React.useState<
InitialState | undefined
>();
try {
initialState = JSON.parse(localStorage.getItem(PERSISTENCE_KEY) || '');
} catch (e) {
// Do nothing
}
React.useEffect(() => {
AsyncStorage.getItem(PERSISTENCE_KEY).then(
data => {
try {
const result = JSON.parse(data || '');
if (result) {
setInitialState(result);
}
} finally {
setIsReady(true);
}
},
() => setIsReady(true)
);
}, []);
if (!isReady) {
return null;
}
function App() {
return (
<NavigationContainer
initialState={initialState}
onStateChange={state =>
localStorage.setItem(PERSISTENCE_KEY, JSON.stringify(state))
AsyncStorage.setItem(PERSISTENCE_KEY, JSON.stringify(state))
}
>
<Stack.Navigator>
@@ -195,4 +202,10 @@ function App() {
);
}
render(<App />, document.getElementById('root'));
const styles = StyleSheet.create({
title: {
fontSize: 24,
fontWeight: 'bold',
marginBottom: 8,
},
});

View File

@@ -0,0 +1,17 @@
/* eslint-disable import/no-commonjs */
/* eslint-env node */
const createExpoWebpackConfigAsync = require('@expo/webpack-config');
module.exports = async function(env, argv) {
const config = await createExpoWebpackConfigAsync(env, argv);
config.module.rules.push({
test: /@navigation-ex/,
use: 'babel-loader',
});
config.resolve.alias['react'] = require.resolve('react');
return config;
};

View File

@@ -0,0 +1,10 @@
{
"name": "@navigation-ex/routers",
"version": "0.0.1",
"main": "src/index",
"license": "MIT",
"dependencies": {
"shortid": "^2.2.14",
"@navigation-ex/core": "^0.0.1"
}
}

View File

@@ -1,22 +1,11 @@
/* eslint-disable react-native/no-inline-styles */
import * as React from 'react';
import shortid from 'shortid';
import {
useNavigationBuilder,
NavigationProp,
NavigationState,
CommonAction,
ParamListBase,
Router,
BaseRouter,
createNavigator,
DefaultRouterOptions,
} from '../src/index';
type Props = DefaultRouterOptions & {
children: React.ReactNode;
};
} from '@navigation-ex/core';
type Action =
| {
@@ -29,47 +18,12 @@ type Action =
}
| { type: 'POP_TO_TOP' };
export type StackNavigationOptions = {
/**
* Title text for the screen.
*/
title?: string;
};
export type StackRouterOptions = DefaultRouterOptions;
export type StackNavigationProp<
ParamList extends ParamListBase,
RouteName extends keyof ParamList = string
> = NavigationProp<
ParamList,
RouteName,
NavigationState,
StackNavigationOptions
> & {
/**
* Push a new screen onto the stack.
*
* @param name Name of the route for the tab.
* @param [params] Params object for the route.
*/
push<RouteName extends keyof ParamList>(
...args: ParamList[RouteName] extends void
? [RouteName]
: [RouteName, ParamList[RouteName]]
): void;
export type StackNavigationState = NavigationState;
/**
* Pop a screen from the stack.
*/
pop(count?: number): void;
/**
* Pop to the first route in the stack, dismissing all other screens.
*/
popToTop(): void;
};
function StackRouter(options: DefaultRouterOptions) {
const router: Router<NavigationState, CommonAction | Action> = {
export default function StackRouter(options: StackRouterOptions) {
const router: Router<StackNavigationState, CommonAction | Action> = {
...BaseRouter,
getInitialState({ routeNames, routeParamList }) {
@@ -257,53 +211,3 @@ function StackRouter(options: DefaultRouterOptions) {
return router;
}
export function StackNavigator(props: Props) {
const { state, descriptors } = useNavigationBuilder<
NavigationState,
StackNavigationOptions,
DefaultRouterOptions
>(StackRouter, props);
return (
<div style={{ position: 'relative' }}>
{state.routes.map((route, i) => (
<div
key={route.key}
style={{
position: 'absolute',
margin: 20,
left: i * 20,
top: i * 20,
padding: 10,
height: 480,
width: 320,
backgroundColor: 'white',
borderRadius: 3,
boxShadow:
'0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23)',
}}
>
{descriptors[route.key].render()}
</div>
))}
<div
style={{
position: 'absolute',
left: 40,
width: 120,
padding: 10,
backgroundColor: 'tomato',
borderRadius: 3,
boxShadow: '0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23)',
}}
>
{descriptors[state.routes[state.index].key].options.title}
</div>
</div>
);
}
export default createNavigator<StackNavigationOptions, typeof StackNavigator>(
StackNavigator
);

View File

@@ -1,22 +1,11 @@
/* eslint-disable react-native/no-inline-styles */
import * as React from 'react';
import shortid from 'shortid';
import {
useNavigationBuilder,
NavigationProp,
CommonAction,
ParamListBase,
Router,
createNavigator,
BaseRouter,
NavigationState,
DefaultRouterOptions,
} from '../src/index';
type Props = TabRouterOptions & {
children: React.ReactNode;
};
Router,
} from '@navigation-ex/core';
type Action = {
type: 'JUMP_TO';
@@ -27,13 +16,6 @@ export type TabRouterOptions = DefaultRouterOptions & {
backBehavior?: 'initialRoute' | 'order' | 'history' | 'none';
};
export type TabNavigationOptions = {
/**
* Title text for the screen.
*/
title?: string;
};
export type TabNavigationState = NavigationState & {
/**
* List of previously visited route keys.
@@ -41,29 +23,7 @@ export type TabNavigationState = NavigationState & {
routeKeyHistory: string[];
};
export type TabNavigationProp<
ParamList extends ParamListBase,
RouteName extends keyof ParamList = string
> = NavigationProp<
ParamList,
RouteName,
TabNavigationState,
TabNavigationOptions
> & {
/**
* Jump to an existing tab.
*
* @param name Name of the route for the tab.
* @param [params] Params object for the route.
*/
jumpTo<RouteName extends Extract<keyof ParamList, string>>(
...args: ParamList[RouteName] extends void
? [RouteName]
: [RouteName, ParamList[RouteName]]
): void;
};
function TabRouter({
export default function TabRouter({
initialRouteName,
backBehavior = 'history',
}: TabRouterOptions) {
@@ -252,33 +212,3 @@ function TabRouter({
return router;
}
export function TabNavigator(props: Props) {
const { state, descriptors } = useNavigationBuilder<
TabNavigationState,
TabNavigationOptions,
TabRouterOptions
>(TabRouter, props);
return (
<div style={{ display: 'flex', flexDirection: 'row', height: '100%' }}>
{state.routes.map((route, i, self) => (
<div
key={route.key}
style={{
width: `${100 / self.length}%`,
padding: 10,
borderRadius: 3,
backgroundColor: i === state.index ? 'tomato' : 'white',
}}
>
{descriptors[route.key].render()}
</div>
))}
</div>
);
}
export default createNavigator<TabNavigationOptions, typeof TabNavigator>(
TabNavigator
);

View File

@@ -0,0 +1,11 @@
export {
default as StackRouter,
StackRouterOptions,
StackNavigationState,
} from './StackRouter';
export {
default as TabRouter,
TabRouterOptions,
TabNavigationState,
} from './TabRouter';

View File

@@ -1,5 +1,9 @@
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@navigation-ex": ["./packages"]
},
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"esModuleInterop": true,

10070
yarn.lock

File diff suppressed because it is too large Load Diff