Update animated components to use TypeScript
This commit is contained in:
parent
f43dc55735
commit
140bcf3675
3 changed files with 84 additions and 70 deletions
|
@ -17,42 +17,37 @@
|
||||||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// @flow
|
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import {View} from 'react-native';
|
import {View, ViewStyle} from 'react-native';
|
||||||
import {List, withTheme} from 'react-native-paper';
|
import {List, withTheme} from 'react-native-paper';
|
||||||
import Collapsible from 'react-native-collapsible';
|
import Collapsible from 'react-native-collapsible';
|
||||||
import * as Animatable from 'react-native-animatable';
|
import * as Animatable from 'react-native-animatable';
|
||||||
import type {CustomThemeType} from '../../managers/ThemeManager';
|
|
||||||
import type {ListIconPropsType} from '../../constants/PaperStyles';
|
|
||||||
|
|
||||||
type PropsType = {
|
type PropsType = {
|
||||||
theme: CustomThemeType,
|
theme: ReactNativePaper.Theme;
|
||||||
title: string,
|
title: string;
|
||||||
subtitle?: string,
|
subtitle?: string;
|
||||||
left?: () => React.Node,
|
style: ViewStyle;
|
||||||
opened?: boolean,
|
left?: (props: {
|
||||||
unmountWhenCollapsed?: boolean,
|
color: string;
|
||||||
children?: React.Node,
|
style?: {
|
||||||
|
marginRight: number;
|
||||||
|
marginVertical?: number;
|
||||||
|
};
|
||||||
|
}) => React.ReactNode;
|
||||||
|
opened?: boolean;
|
||||||
|
unmountWhenCollapsed?: boolean;
|
||||||
|
children?: React.ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
type StateType = {
|
type StateType = {
|
||||||
expanded: boolean,
|
expanded: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const AnimatedListIcon = Animatable.createAnimatableComponent(List.Icon);
|
const AnimatedListIcon = Animatable.createAnimatableComponent(List.Icon);
|
||||||
|
|
||||||
class AnimatedAccordion extends React.Component<PropsType, StateType> {
|
class AnimatedAccordion extends React.Component<PropsType, StateType> {
|
||||||
static defaultProps = {
|
chevronRef: {current: null | (typeof AnimatedListIcon & List.Icon)};
|
||||||
subtitle: '',
|
|
||||||
left: null,
|
|
||||||
opened: null,
|
|
||||||
unmountWhenCollapsed: false,
|
|
||||||
children: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
chevronRef: {current: null | AnimatedListIcon};
|
|
||||||
|
|
||||||
chevronIcon: string;
|
chevronIcon: string;
|
||||||
|
|
||||||
|
@ -62,6 +57,9 @@ class AnimatedAccordion extends React.Component<PropsType, StateType> {
|
||||||
|
|
||||||
constructor(props: PropsType) {
|
constructor(props: PropsType) {
|
||||||
super(props);
|
super(props);
|
||||||
|
this.chevronIcon = '';
|
||||||
|
this.animStart = '';
|
||||||
|
this.animEnd = '';
|
||||||
this.state = {
|
this.state = {
|
||||||
expanded: props.opened != null ? props.opened : false,
|
expanded: props.opened != null ? props.opened : false,
|
||||||
};
|
};
|
||||||
|
@ -71,8 +69,9 @@ class AnimatedAccordion extends React.Component<PropsType, StateType> {
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps: PropsType): boolean {
|
shouldComponentUpdate(nextProps: PropsType): boolean {
|
||||||
const {state, props} = this;
|
const {state, props} = this;
|
||||||
if (nextProps.opened != null && nextProps.opened !== props.opened)
|
if (nextProps.opened != null && nextProps.opened !== props.opened) {
|
||||||
state.expanded = nextProps.opened;
|
state.expanded = nextProps.opened;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,17 +100,17 @@ class AnimatedAccordion extends React.Component<PropsType, StateType> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
render(): React.Node {
|
render() {
|
||||||
const {props, state} = this;
|
const {props, state} = this;
|
||||||
const {colors} = props.theme;
|
const {colors} = props.theme;
|
||||||
return (
|
return (
|
||||||
<View>
|
<View style={props.style}>
|
||||||
<List.Item
|
<List.Item
|
||||||
title={props.title}
|
title={props.title}
|
||||||
subtitle={props.subtitle}
|
description={props.subtitle}
|
||||||
titleStyle={state.expanded ? {color: colors.primary} : null}
|
titleStyle={state.expanded ? {color: colors.primary} : null}
|
||||||
onPress={this.toggleAccordion}
|
onPress={this.toggleAccordion}
|
||||||
right={(iconProps: ListIconPropsType): React.Node => (
|
right={(iconProps) => (
|
||||||
<AnimatedListIcon
|
<AnimatedListIcon
|
||||||
ref={this.chevronRef}
|
ref={this.chevronRef}
|
||||||
style={iconProps.style}
|
style={iconProps.style}
|
|
@ -17,29 +17,30 @@
|
||||||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// @flow
|
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import {StyleSheet, View} from 'react-native';
|
import {
|
||||||
|
NativeScrollEvent,
|
||||||
|
NativeSyntheticEvent,
|
||||||
|
StyleSheet,
|
||||||
|
View,
|
||||||
|
} from 'react-native';
|
||||||
import {FAB, IconButton, Surface, withTheme} from 'react-native-paper';
|
import {FAB, IconButton, Surface, withTheme} from 'react-native-paper';
|
||||||
import * as Animatable from 'react-native-animatable';
|
import * as Animatable from 'react-native-animatable';
|
||||||
import {StackNavigationProp} from '@react-navigation/stack';
|
import {StackNavigationProp} from '@react-navigation/stack';
|
||||||
import AutoHideHandler from '../../utils/AutoHideHandler';
|
import AutoHideHandler from '../../utils/AutoHideHandler';
|
||||||
import CustomTabBar from '../Tabbar/CustomTabBar';
|
import CustomTabBar from '../Tabbar/CustomTabBar';
|
||||||
import type {CustomThemeType} from '../../managers/ThemeManager';
|
|
||||||
import type {OnScrollType} from '../../utils/AutoHideHandler';
|
|
||||||
|
|
||||||
const AnimatedFAB = Animatable.createAnimatableComponent(FAB);
|
const AnimatedFAB = Animatable.createAnimatableComponent(FAB);
|
||||||
|
|
||||||
type PropsType = {
|
type PropsType = {
|
||||||
navigation: StackNavigationProp,
|
navigation: StackNavigationProp<any>;
|
||||||
theme: CustomThemeType,
|
theme: ReactNativePaper.Theme;
|
||||||
onPress: (action: string, data?: string) => void,
|
onPress: (action: string, data?: string) => void;
|
||||||
seekAttention: boolean,
|
seekAttention: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
type StateType = {
|
type StateType = {
|
||||||
currentMode: string,
|
currentMode: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const DISPLAY_MODES = {
|
const DISPLAY_MODES = {
|
||||||
|
@ -78,14 +79,14 @@ const styles = StyleSheet.create({
|
||||||
});
|
});
|
||||||
|
|
||||||
class AnimatedBottomBar extends React.Component<PropsType, StateType> {
|
class AnimatedBottomBar extends React.Component<PropsType, StateType> {
|
||||||
ref: {current: null | Animatable.View};
|
ref: {current: null | (Animatable.View & View)};
|
||||||
|
|
||||||
hideHandler: AutoHideHandler;
|
hideHandler: AutoHideHandler;
|
||||||
|
|
||||||
displayModeIcons: {[key: string]: string};
|
displayModeIcons: {[key: string]: string};
|
||||||
|
|
||||||
constructor() {
|
constructor(props: PropsType) {
|
||||||
super();
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
currentMode: DISPLAY_MODES.WEEK,
|
currentMode: DISPLAY_MODES.WEEK,
|
||||||
};
|
};
|
||||||
|
@ -108,13 +109,17 @@ class AnimatedBottomBar extends React.Component<PropsType, StateType> {
|
||||||
}
|
}
|
||||||
|
|
||||||
onHideChange = (shouldHide: boolean) => {
|
onHideChange = (shouldHide: boolean) => {
|
||||||
if (this.ref.current != null) {
|
const ref = this.ref;
|
||||||
if (shouldHide) this.ref.current.fadeOutDown(500);
|
if (ref && ref.current && ref.current.fadeOutDown && ref.current.fadeInUp) {
|
||||||
else this.ref.current.fadeInUp(500);
|
if (shouldHide) {
|
||||||
|
ref.current.fadeOutDown(500);
|
||||||
|
} else {
|
||||||
|
ref.current.fadeInUp(500);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
onScroll = (event: OnScrollType) => {
|
onScroll = (event: NativeSyntheticEvent<NativeScrollEvent>) => {
|
||||||
this.hideHandler.onScroll(event);
|
this.hideHandler.onScroll(event);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -139,7 +144,7 @@ class AnimatedBottomBar extends React.Component<PropsType, StateType> {
|
||||||
props.onPress('changeView', newMode);
|
props.onPress('changeView', newMode);
|
||||||
};
|
};
|
||||||
|
|
||||||
render(): React.Node {
|
render() {
|
||||||
const {props, state} = this;
|
const {props, state} = this;
|
||||||
const buttonColor = props.theme.colors.primary;
|
const buttonColor = props.theme.colors.primary;
|
||||||
return (
|
return (
|
|
@ -17,22 +17,23 @@
|
||||||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// @flow
|
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import {StyleSheet} from 'react-native';
|
import {
|
||||||
|
NativeScrollEvent,
|
||||||
|
NativeSyntheticEvent,
|
||||||
|
StyleSheet,
|
||||||
|
View,
|
||||||
|
} from 'react-native';
|
||||||
import {FAB} from 'react-native-paper';
|
import {FAB} from 'react-native-paper';
|
||||||
import * as Animatable from 'react-native-animatable';
|
import * as Animatable from 'react-native-animatable';
|
||||||
import AutoHideHandler from '../../utils/AutoHideHandler';
|
import AutoHideHandler from '../../utils/AutoHideHandler';
|
||||||
import CustomTabBar from '../Tabbar/CustomTabBar';
|
import CustomTabBar from '../Tabbar/CustomTabBar';
|
||||||
|
|
||||||
type PropsType = {
|
type PropsType = {
|
||||||
icon: string,
|
icon: string;
|
||||||
onPress: () => void,
|
onPress: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const AnimatedFab = Animatable.createAnimatableComponent(FAB);
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
fab: {
|
fab: {
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
|
@ -42,41 +43,50 @@ const styles = StyleSheet.create({
|
||||||
});
|
});
|
||||||
|
|
||||||
export default class AnimatedFAB extends React.Component<PropsType> {
|
export default class AnimatedFAB extends React.Component<PropsType> {
|
||||||
ref: {current: null | Animatable.View};
|
ref: {current: null | (Animatable.View & View)};
|
||||||
|
|
||||||
hideHandler: AutoHideHandler;
|
hideHandler: AutoHideHandler;
|
||||||
|
|
||||||
constructor() {
|
constructor(props: PropsType) {
|
||||||
super();
|
super(props);
|
||||||
this.ref = React.createRef();
|
this.ref = React.createRef();
|
||||||
this.hideHandler = new AutoHideHandler(false);
|
this.hideHandler = new AutoHideHandler(false);
|
||||||
this.hideHandler.addListener(this.onHideChange);
|
this.hideHandler.addListener(this.onHideChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
onScroll = (event: SyntheticEvent<EventTarget>) => {
|
onScroll = (event: NativeSyntheticEvent<NativeScrollEvent>) => {
|
||||||
this.hideHandler.onScroll(event);
|
this.hideHandler.onScroll(event);
|
||||||
};
|
};
|
||||||
|
|
||||||
onHideChange = (shouldHide: boolean) => {
|
onHideChange = (shouldHide: boolean) => {
|
||||||
if (this.ref.current != null) {
|
const ref = this.ref;
|
||||||
if (shouldHide) this.ref.current.bounceOutDown(1000);
|
if (
|
||||||
else this.ref.current.bounceInUp(1000);
|
ref &&
|
||||||
|
ref.current &&
|
||||||
|
ref.current.bounceOutDown &&
|
||||||
|
ref.current.bounceInUp
|
||||||
|
) {
|
||||||
|
if (shouldHide) {
|
||||||
|
ref.current.bounceOutDown(1000);
|
||||||
|
} else {
|
||||||
|
ref.current.bounceInUp(1000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
render(): React.Node {
|
render() {
|
||||||
const {props} = this;
|
const {props} = this;
|
||||||
return (
|
return (
|
||||||
<AnimatedFab
|
<Animatable.View ref={this.ref} useNativeDriver={true}>
|
||||||
ref={this.ref}
|
<FAB
|
||||||
useNativeDriver
|
icon={props.icon}
|
||||||
icon={props.icon}
|
onPress={props.onPress}
|
||||||
onPress={props.onPress}
|
style={{
|
||||||
style={{
|
...styles.fab,
|
||||||
...styles.fab,
|
bottom: CustomTabBar.TAB_BAR_HEIGHT,
|
||||||
bottom: CustomTabBar.TAB_BAR_HEIGHT,
|
}}
|
||||||
}}
|
/>
|
||||||
/>
|
</Animatable.View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue