/
StackManager.tsx
109 lines (89 loc) · 3.05 KB
/
StackManager.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import React from 'react';
import { generateId, isDevMode } from '../utils';
import { RouteManagerContext, RouteManagerContextState } from './RouteManagerContext';
import { View } from './View';
import { ViewItem } from './ViewItem';
import { ViewTransitionManager } from './ViewTransitionManager';
interface StackManagerProps {
id?: string;
routeManager: RouteManagerContextState;
children?: React.ReactNode;
}
interface StackManagerState { }
class StackManagerInner extends React.Component<StackManagerProps, StackManagerState> {
routerOutletEl: React.RefObject<HTMLIonRouterOutletElement> = React.createRef();
id: string;
constructor(props: StackManagerProps) {
super(props);
this.id = this.props.id || generateId();
this.handleViewSync = this.handleViewSync.bind(this);
this.handleHideView = this.handleHideView.bind(this);
this.state = {};
}
componentDidMount() {
this.props.routeManager.setupIonRouter(this.id, this.props.children, this.routerOutletEl.current!);
}
static getDerivedStateFromProps(props: StackManagerProps, state: StackManagerState) {
props.routeManager.syncRoute(props.children);
return state;
}
componentWillUnmount() {
this.props.routeManager.removeViewStack(this.id);
}
handleViewSync(page: HTMLElement, viewId: string) {
this.props.routeManager.syncView(page, viewId);
}
handleHideView(viewId: string) {
this.props.routeManager.hideView(viewId);
}
renderChild(item: ViewItem, route: any) {
const component = React.cloneElement(route, {
computedMatch: item.routeData.match
});
return component;
}
render() {
const routeManager = this.props.routeManager;
const viewStack = routeManager.viewStacks.get(this.id);
const views = (viewStack || { views: [] }).views.filter(x => x.show);
const ionRouterOutlet = React.Children.only(this.props.children) as React.ReactElement;
const childElements = views.map(view => {
const route = routeManager.getRoute(view.routeId);
return (
<ViewTransitionManager
id={view.id}
key={view.key}
mount={view.mount}
>
<View
onViewSync={this.handleViewSync}
onHideView={this.handleHideView}
view={view}
route={route}
>
{this.renderChild(view, route)}
</View>
</ViewTransitionManager>
);
});
const elementProps: any = {
ref: this.routerOutletEl
};
if (ionRouterOutlet.props.forwardedRef) {
ionRouterOutlet.props.forwardedRef.current = this.routerOutletEl;
}
if (isDevMode()) {
elementProps['data-stack-id'] = this.id;
}
const routerOutletChild = React.cloneElement(ionRouterOutlet, elementProps, childElements);
return routerOutletChild;
}
}
const withContext = (Component: any) => {
return (props: any) => (
<RouteManagerContext.Consumer>
{context => <Component {...props} routeManager={context} />}
</RouteManagerContext.Consumer>
);
};
export const StackManager = withContext(StackManagerInner);