/
IonTabBar.tsx
117 lines (99 loc) · 3.28 KB
/
IonTabBar.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
110
111
112
113
114
115
116
117
import { JSX as LocalJSX } from '@ionic/core';
import React, { useContext } from 'react';
import { NavContext } from '../../contexts/NavContext';
import { IonTabBarInner } from '../inner-proxies';
import { IonTabButton } from '../proxies';
type Props = LocalJSX.IonTabBar & {
currentPath?: string;
slot?: 'bottom' | 'top';
};
interface Tab {
originalHref: string;
currentHref: string;
}
interface State {
activeTab: string | undefined;
tabs: { [key: string]: Tab };
}
const IonTabBarUnwrapped = /*@__PURE__*/(() => class extends React.Component<Props, State> {
context!: React.ContextType<typeof NavContext>;
constructor(props: Props) {
super(props);
const tabActiveUrls: { [key: string]: Tab } = {};
React.Children.forEach(this.props.children, (child: any) => {
if (child != null && typeof child === 'object' && child.props && child.type === IonTabButton) {
tabActiveUrls[child.props.tab] = {
originalHref: child.props.href,
currentHref: child.props.href
};
}
});
this.state = {
activeTab: undefined,
tabs: tabActiveUrls
};
}
static getDerivedStateFromProps(props: Props, state: State) {
const activeTab = Object.keys(state.tabs)
.find(key => {
const href = state.tabs[key].originalHref;
return props.currentPath!.startsWith(href);
});
if (activeTab === undefined || (activeTab === state.activeTab && state.tabs[activeTab].currentHref === props.currentPath)) {
return null;
}
return {
activeTab,
tabs: {
...state.tabs,
[activeTab]: {
originalHref: state.tabs[activeTab].originalHref,
currentHref: props.currentPath
}
}
};
}
private onTabButtonClick = (e: CustomEvent<{ href: string, selected: boolean, tab: string }>) => {
if (this.state.activeTab === e.detail.tab) {
const originalHref = this.state.tabs[e.detail.tab].originalHref;
if (this.context.hasIonicRouter()) {
this.context.goBack(originalHref);
} else {
this.context.navigate(originalHref, 'back');
}
} else {
this.context.navigate(this.state.tabs[e.detail.tab].currentHref, 'none');
}
}
private renderChild = (activeTab: string | null | undefined) => (child: (React.ReactElement<LocalJSX.IonTabButton & { onIonTabButtonClick: (e: CustomEvent) => void }>) | null | undefined) => {
if (child != null && child.props && child.type === IonTabButton) {
const href = (child.props.tab === activeTab) ? this.props.currentPath : (this.state.tabs[child.props.tab!].currentHref);
return React.cloneElement(child, {
href,
onIonTabButtonClick: this.onTabButtonClick
});
}
return null;
}
render() {
return (
<IonTabBarInner {...this.props} selectedTab={this.state.activeTab}>
{React.Children.map(this.props.children as any, this.renderChild(this.state.activeTab))}
</IonTabBarInner>
);
}
static get contextType() {
return NavContext;
}
})();
export const IonTabBar: React.FC<Props> = props => {
const context = useContext(NavContext);
return (
<IonTabBarUnwrapped
{...props as any}
currentPath={props.currentPath || context.currentPath}
>
{props.children}
</IonTabBarUnwrapped>
);
};