Skip to content
This repository was archived by the owner on Nov 3, 2025. It is now read-only.

Commit 62d419c

Browse files
authored
Merge pull request #71 from tpucci/canal/stop/type
Add FullScreen Portal
2 parents f76f3b8 + 257df96 commit 62d419c

18 files changed

Lines changed: 439 additions & 16 deletions

example/src/App.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
import React, { Component } from 'react';
22
import { SignIn } from './canals/SignIn';
3+
import { FullScreenPortal } from 'react-gondola';
34

45
interface IProps {}
56
export default class App extends Component<IProps> {
67
render() {
7-
return <SignIn />;
8+
return (
9+
<FullScreenPortal>
10+
<SignIn />
11+
</FullScreenPortal>
12+
);
813
}
914
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import React, { Component } from 'react';
2+
import { StyleSheet, Text, View } from 'react-native';
3+
4+
interface IProps {}
5+
export class Confirm extends Component<IProps> {
6+
render() {
7+
return (
8+
<View style={styles.container}>
9+
<Text>Confim</Text>
10+
</View>
11+
);
12+
}
13+
}
14+
15+
const styles = StyleSheet.create({
16+
container: {
17+
alignItems: 'center',
18+
backgroundColor: '#FFFF99',
19+
flex: 1,
20+
justifyContent: 'center'
21+
}
22+
});

example/src/canals/SignIn/SignIn.tsx

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React from 'react';
22
import { createCanal } from 'react-gondola';
33
import { FirstName } from './FirstName';
44
import { LastName } from './LastName';
5+
import { Confirm } from './Confirm';
56
import { Observer } from 'mobx-react/native';
67
import { fromStream } from 'mobx-utils';
78
import { interval } from 'rxjs';
@@ -10,16 +11,26 @@ import { map } from 'rxjs/operators';
1011
// @ts-ignore
1112
const SignInCanal = createCanal([
1213
{ name: 'firstName', Component: FirstName },
13-
{ name: 'lastName', Component: LastName }
14+
{ name: 'lastName', Component: LastName },
15+
{ name: 'confirm', Component: Confirm, isFullScreen: true }
1416
]);
1517

1618
export const SignIn = () => {
17-
const delayedAuth = fromStream(
19+
const lastNameAuth = fromStream(
20+
interval(1000).pipe(map(tick => tick % 4 === 0 || (tick + 1) % 4 === 0))
21+
);
22+
const confirmAuth = fromStream(
1823
interval(1000).pipe(map(tick => tick % 2 === 0))
1924
);
2025
return (
2126
<Observer>
22-
{() => <SignInCanal firstName lastName={delayedAuth.current} />}
27+
{() => (
28+
<SignInCanal
29+
firstName
30+
lastName={lastNameAuth.current}
31+
confirm={confirmAuth.current}
32+
/>
33+
)}
2334
</Observer>
2435
);
2536
};
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import React from 'react';
2+
import TestRenderer from 'react-test-renderer';
3+
4+
import { Confirm } from '../Confirm';
5+
6+
describe('Confirm', () => {
7+
it('renders correctly', () => {
8+
const testRenderer = TestRenderer.create(<Confirm />);
9+
expect(testRenderer.toJSON()).toMatchSnapshot();
10+
});
11+
});
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`Confirm renders correctly 1`] = `
4+
<View
5+
style={
6+
Object {
7+
"alignItems": "center",
8+
"backgroundColor": "#FFFF99",
9+
"flex": 1,
10+
"justifyContent": "center",
11+
}
12+
}
13+
>
14+
<Text>
15+
Confim
16+
</Text>
17+
</View>
18+
`;

jest.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@ module.exports = {
1313
statements: 100,
1414
},
1515
},
16+
testPathIgnorePatterns: ['/node_modules/', '/__tests__/utils'],
1617
};

jest/setup.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@ import { configure } from 'mobx';
33
configure({
44
enforceActions: 'observed',
55
});
6+
7+
Date.now = jest.fn(() => 0);

src/FullScreenPortal.tsx

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import React, { Component as ReactComponent, Fragment } from 'react';
2+
import { View, StyleSheet } from 'react-native';
3+
import { Observer } from 'mobx-react/native';
4+
import { fromStream } from 'mobx-utils';
5+
import { Navigation } from './Navigation';
6+
7+
export class FullScreenPortal extends ReactComponent {
8+
fullScreenStack = fromStream(Navigation.getInstance().fullSceenStack$);
9+
10+
render() {
11+
return (
12+
<View style={StyleSheet.absoluteFill}>
13+
<Fragment>{this.props.children}</Fragment>
14+
<Observer>
15+
{() => {
16+
if (this.fullScreenStack.current) {
17+
return (
18+
this.fullScreenStack.current &&
19+
this.fullScreenStack.current.map(({ Component, name }) => (
20+
<View style={StyleSheet.absoluteFill} key={name}>
21+
<Component />
22+
</View>
23+
))
24+
);
25+
}
26+
return null;
27+
}}
28+
</Observer>
29+
</View>
30+
);
31+
}
32+
}

src/Navigation.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { Subject, Observable } from 'rxjs';
2+
import { ComponentType } from 'react';
3+
import { mergeAll, map, scan } from 'rxjs/operators';
4+
5+
export interface IStop {
6+
name: string;
7+
Component: ComponentType;
8+
isFullScreen?: boolean;
9+
}
10+
11+
type Stack = IStop[];
12+
13+
interface IFullScreenStackProperties {
14+
canalId: string;
15+
fullScreenStack: Stack;
16+
}
17+
18+
interface IFullScreenStackMap {
19+
[canalId: string]: Stack;
20+
}
21+
22+
export class Navigation {
23+
static getInstance() {
24+
if (Navigation.instance) {
25+
return Navigation.instance;
26+
}
27+
Navigation.instance = new Navigation();
28+
return Navigation.instance;
29+
}
30+
private static instance: Navigation;
31+
32+
canalsFullScreenStackProperties$ = new Subject<
33+
Observable<IFullScreenStackProperties>
34+
>();
35+
36+
fullSceenStack$: Observable<
37+
Stack
38+
> = this.canalsFullScreenStackProperties$.pipe(
39+
mergeAll(),
40+
scan(
41+
(
42+
fullScreenStackMap: IFullScreenStackMap,
43+
fullScreenStackProperties: IFullScreenStackProperties
44+
) => ({
45+
...fullScreenStackMap,
46+
[fullScreenStackProperties.canalId]:
47+
fullScreenStackProperties.fullScreenStack
48+
}),
49+
{}
50+
),
51+
map(fullScreenStackMap =>
52+
Object.keys(fullScreenStackMap).reduce(
53+
(fullScreenStack: Stack, canalId: string) =>
54+
fullScreenStack.concat(fullScreenStackMap[canalId]),
55+
[]
56+
)
57+
)
58+
);
59+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import React from 'react';
2+
import TestRenderer from 'react-test-renderer';
3+
4+
import { FullScreenPortal } from '../FullScreenPortal';
5+
6+
describe('FullScreenPortal', () => {
7+
it('renders the full screen portal', () => {
8+
const testRenderer = TestRenderer.create(<FullScreenPortal />);
9+
expect(testRenderer.toJSON()).toMatchSnapshot();
10+
});
11+
});

0 commit comments

Comments
 (0)