|
@@ -18,10 +18,13 @@
|
18
|
18
|
*/
|
19
|
19
|
|
20
|
20
|
import * as React from 'react';
|
21
|
|
-import { View, ViewStyle } from 'react-native';
|
|
21
|
+import { View, ViewProps, ViewStyle } from 'react-native';
|
22
|
22
|
import { List, withTheme } from 'react-native-paper';
|
23
|
23
|
import Collapsible from 'react-native-collapsible';
|
24
|
24
|
import * as Animatable from 'react-native-animatable';
|
|
25
|
+import { AnimatableProperties } from 'react-native-animatable';
|
|
26
|
+import { ClassicComponent } from 'react';
|
|
27
|
+import GENERAL_STYLES from '../../constants/Styles';
|
25
|
28
|
|
26
|
29
|
type PropsType = {
|
27
|
30
|
theme: ReactNativePaper.Theme;
|
|
@@ -44,10 +47,13 @@ type StateType = {
|
44
|
47
|
expanded: boolean;
|
45
|
48
|
};
|
46
|
49
|
|
47
|
|
-const AnimatedListIcon = Animatable.createAnimatableComponent(List.Icon);
|
48
|
|
-
|
49
|
50
|
class AnimatedAccordion extends React.Component<PropsType, StateType> {
|
50
|
|
- chevronRef: { current: null | (typeof AnimatedListIcon & List.Icon) };
|
|
51
|
+ viewRef:
|
|
52
|
+ | null
|
|
53
|
+ | (ClassicComponent<AnimatableProperties<ViewStyle>> & ViewProps);
|
|
54
|
+ handleViewRef = (
|
|
55
|
+ ref: ClassicComponent<AnimatableProperties<ViewStyle>> & ViewProps
|
|
56
|
+ ) => (this.viewRef = ref);
|
51
|
57
|
|
52
|
58
|
chevronIcon: string;
|
53
|
59
|
|
|
@@ -55,6 +61,37 @@ class AnimatedAccordion extends React.Component<PropsType, StateType> {
|
55
|
61
|
|
56
|
62
|
animEnd: string;
|
57
|
63
|
|
|
64
|
+ getAccordionAnimation():
|
|
65
|
+ | Animatable.Animation
|
|
66
|
+ | string
|
|
67
|
+ | Animatable.CustomAnimation {
|
|
68
|
+ // I don't knwo why ts is complaining
|
|
69
|
+ // The type definitions must be broken because this is a valid style and it works
|
|
70
|
+ if (this.state.expanded) {
|
|
71
|
+ return {
|
|
72
|
+ from: {
|
|
73
|
+ // @ts-ignore
|
|
74
|
+ rotate: this.animStart,
|
|
75
|
+ },
|
|
76
|
+ to: {
|
|
77
|
+ // @ts-ignore
|
|
78
|
+ rotate: this.animEnd,
|
|
79
|
+ },
|
|
80
|
+ };
|
|
81
|
+ } else {
|
|
82
|
+ return {
|
|
83
|
+ from: {
|
|
84
|
+ // @ts-ignore
|
|
85
|
+ rotate: this.animEnd,
|
|
86
|
+ },
|
|
87
|
+ to: {
|
|
88
|
+ // @ts-ignore
|
|
89
|
+ rotate: this.animStart,
|
|
90
|
+ },
|
|
91
|
+ };
|
|
92
|
+ }
|
|
93
|
+ }
|
|
94
|
+
|
58
|
95
|
constructor(props: PropsType) {
|
59
|
96
|
super(props);
|
60
|
97
|
this.chevronIcon = '';
|
|
@@ -63,12 +100,13 @@ class AnimatedAccordion extends React.Component<PropsType, StateType> {
|
63
|
100
|
this.state = {
|
64
|
101
|
expanded: props.opened != null ? props.opened : false,
|
65
|
102
|
};
|
66
|
|
- this.chevronRef = React.createRef();
|
|
103
|
+ this.viewRef = null;
|
67
|
104
|
this.setupChevron();
|
68
|
105
|
}
|
69
|
106
|
|
70
|
107
|
shouldComponentUpdate(nextProps: PropsType): boolean {
|
71
|
108
|
const { state, props } = this;
|
|
109
|
+ // TODO refactor this, it shouldn't even work
|
72
|
110
|
if (nextProps.opened != null && nextProps.opened !== props.opened) {
|
73
|
111
|
state.expanded = nextProps.opened;
|
74
|
112
|
}
|
|
@@ -89,15 +127,10 @@ class AnimatedAccordion extends React.Component<PropsType, StateType> {
|
89
|
127
|
}
|
90
|
128
|
|
91
|
129
|
toggleAccordion = () => {
|
92
|
|
- const { expanded } = this.state;
|
93
|
|
- if (this.chevronRef.current != null) {
|
94
|
|
- this.chevronRef.current.transitionTo({
|
95
|
|
- rotate: expanded ? this.animStart : this.animEnd,
|
96
|
|
- });
|
97
|
|
- this.setState((prevState: StateType): { expanded: boolean } => ({
|
98
|
|
- expanded: !prevState.expanded,
|
99
|
|
- }));
|
100
|
|
- }
|
|
130
|
+ // const { expanded } = this.state;
|
|
131
|
+ this.setState((prevState: StateType): { expanded: boolean } => ({
|
|
132
|
+ expanded: !prevState.expanded,
|
|
133
|
+ }));
|
101
|
134
|
};
|
102
|
135
|
|
103
|
136
|
render() {
|
|
@@ -111,13 +144,17 @@ class AnimatedAccordion extends React.Component<PropsType, StateType> {
|
111
|
144
|
titleStyle={state.expanded ? { color: colors.primary } : null}
|
112
|
145
|
onPress={this.toggleAccordion}
|
113
|
146
|
right={(iconProps) => (
|
114
|
|
- <AnimatedListIcon
|
115
|
|
- ref={this.chevronRef}
|
116
|
|
- style={iconProps.style}
|
117
|
|
- icon={this.chevronIcon}
|
118
|
|
- color={state.expanded ? colors.primary : iconProps.color}
|
119
|
|
- useNativeDriver
|
120
|
|
- />
|
|
147
|
+ <Animatable.View
|
|
148
|
+ animation={this.getAccordionAnimation()}
|
|
149
|
+ duration={300}
|
|
150
|
+ useNativeDriver={true}
|
|
151
|
+ >
|
|
152
|
+ <List.Icon
|
|
153
|
+ style={{ ...iconProps.style, ...GENERAL_STYLES.center }}
|
|
154
|
+ icon={this.chevronIcon}
|
|
155
|
+ color={state.expanded ? colors.primary : iconProps.color}
|
|
156
|
+ />
|
|
157
|
+ </Animatable.View>
|
121
|
158
|
)}
|
122
|
159
|
left={props.left}
|
123
|
160
|
/>
|