1
- import Animated from './Animated'
2
- import AnimatedValue from './AnimatedValue'
3
- import AnimatedArray from './AnimatedArray'
4
- import Interpolation from './Interpolation'
5
- import {
6
- interpolation as interp ,
7
- now ,
8
- colorNames ,
9
- requestFrame as raf ,
10
- } from './Globals'
11
- import { start } from './FrameLoop'
12
1
import {
13
- interpolateTo ,
14
- withDefault ,
15
- toArray ,
16
2
callProp ,
3
+ interpolateTo ,
17
4
is ,
5
+ toArray ,
6
+ withDefault ,
18
7
} from '../shared/helpers'
8
+ import AnimatedArray from './AnimatedArray'
9
+ import AnimatedValue from './AnimatedValue'
10
+ import { start } from './FrameLoop'
11
+ import { colorNames , interpolation as interp , now } from './Globals'
12
+
13
+ type FinishedCallback = ( finished ?: boolean ) => void
14
+
15
+ type AnimationsFor < P > = { [ Key in keyof P ] : any }
16
+
17
+ type ValuesFor < P > = { [ Key in keyof P ] : any }
18
+
19
+ type InterpolationsFor < P > = {
20
+ [ Key in keyof P ] : P [ Key ] extends ArrayLike < any >
21
+ ? AnimatedArray
22
+ : AnimatedValue
23
+ }
19
24
20
25
let G = 0
21
- export default class Controller {
22
- constructor ( props ) {
26
+ class Controller < P extends any = { } > {
27
+ id : number
28
+
29
+ idle = true
30
+ hasChanged = false
31
+ guid = 0
32
+ local = 0
33
+ props : P = { } as P
34
+ merged : any = { }
35
+ animations = { } as AnimationsFor < P >
36
+ interpolations = { } as InterpolationsFor < P >
37
+ values = { } as ValuesFor < P >
38
+ configs : any = [ ]
39
+ listeners : FinishedCallback [ ] = [ ]
40
+ queue : any [ ] = [ ]
41
+ localQueue ?: any [ ]
42
+
43
+ constructor ( ) {
23
44
this . id = G ++
24
- this . idle = true
25
- this . hasChanged = false
26
- this . guid = 0
27
- this . local = 0
28
- this . props = { }
29
- this . merged = { }
30
- this . animations = { }
31
- this . interpolations = { }
32
- this . values = { }
33
- this . configs = [ ]
34
- this . listeners = [ ]
35
- this . queue = [ ]
36
- if ( props ) this . update ( props )
37
45
}
38
46
39
47
/** update(props)
40
48
* This function filters input props and creates an array of tasks which are executed in .start()
41
49
* Each task is allowed to carry a delay, which means it can execute asnychroneously */
42
- update ( args ) {
50
+ update ( args ?: P ) {
43
51
//this._id = n + this.id
44
52
45
53
if ( ! args ) return this
46
54
// Extract delay and the to-prop from props
47
- const { delay = 0 , to, ...props } = interpolateTo ( args )
55
+ const { delay = 0 , to, ...props } = interpolateTo ( args ) as any
48
56
if ( is . arr ( to ) || is . fun ( to ) ) {
49
57
// If config is either a function or an array queue it up as is
50
58
this . queue . push ( { ...props , delay, to } )
51
59
} else if ( to ) {
52
60
// Otherwise go through each key since it could be delayed individually
53
- let merge = { }
61
+ let merge : any = { }
54
62
Object . entries ( to ) . forEach ( ( [ k , v ] ) => {
55
63
// Fetch delay and create an entry, consisting of the to-props, the delay, and basic props
56
64
const entry = { to : { [ k ] : v } , delay : callProp ( delay , k ) , ...props }
@@ -71,7 +79,7 @@ export default class Controller {
71
79
72
80
/** start(onEnd)
73
81
* This function either executes a queue, if present, or starts the frameloop, which animates */
74
- start ( onEnd ) {
82
+ start ( onEnd ?: FinishedCallback ) {
75
83
// If a queue is present we must excecute it
76
84
if ( this . queue . length ) {
77
85
this . idle = false
@@ -92,7 +100,7 @@ export default class Controller {
92
100
93
101
// Go through each entry and execute it
94
102
queue . forEach ( ( { delay, ...props } , index ) => {
95
- const cb = finished => {
103
+ const cb : FinishedCallback = finished => {
96
104
if ( index === queue . length - 1 && local === this . guid && finished ) {
97
105
this . idle = true
98
106
if ( this . props . onRest ) this . props . onRest ( this . merged )
@@ -122,43 +130,45 @@ export default class Controller {
122
130
return this
123
131
}
124
132
125
- stop ( finished ) {
133
+ stop ( finished ?: boolean ) {
126
134
this . listeners . forEach ( onEnd => onEnd ( finished ) )
127
135
this . listeners = [ ]
128
136
return this
129
137
}
130
138
131
- runAsync ( { delay, ...props } , onEnd ) {
139
+ runAsync ( { delay, ...props } : P , onEnd : FinishedCallback ) {
132
140
const local = this . local
133
141
// If "to" is either a function or an array it will be processed async, therefor "to" should be empty right now
134
142
// If the view relies on certain values "from" has to be present
135
- let queue = Promise . resolve ( )
143
+ let queue = Promise . resolve ( undefined )
136
144
if ( is . arr ( props . to ) ) {
137
145
for ( let i = 0 ; i < props . to . length ; i ++ ) {
138
146
const index = i
139
- const last = index === props . to . length - 1
140
147
const fresh = { ...props , to : props . to [ index ] }
141
148
if ( is . arr ( fresh . config ) ) fresh . config = fresh . config [ index ]
142
- queue = queue . then ( ( ) => {
143
- //this.stop()
144
- if ( local === this . guid )
145
- return new Promise ( r => this . diff ( interpolateTo ( fresh ) ) . start ( r ) )
146
- } )
149
+ queue = queue . then (
150
+ ( ) : Promise < any > | void => {
151
+ //this.stop()
152
+ if ( local === this . guid )
153
+ return new Promise ( r => this . diff ( interpolateTo ( fresh ) ) . start ( r ) )
154
+ }
155
+ )
147
156
}
148
157
} else if ( is . fun ( props . to ) ) {
149
158
let index = 0
150
- let last = undefined
159
+ let last : Promise < any >
151
160
queue = queue . then ( ( ) =>
152
161
props
153
162
. to (
154
163
// next(props)
155
- p => {
164
+ ( p : P ) => {
156
165
const fresh = { ...props , ...interpolateTo ( p ) }
157
166
if ( is . arr ( fresh . config ) ) fresh . config = fresh . config [ index ]
158
167
index ++
159
168
//this.stop()
160
169
if ( local === this . guid )
161
170
return ( last = new Promise ( r => this . diff ( fresh ) . start ( r ) ) )
171
+ return
162
172
} ,
163
173
// cancel()
164
174
( finished = true ) => this . stop ( finished )
@@ -169,7 +179,7 @@ export default class Controller {
169
179
queue . then ( onEnd )
170
180
}
171
181
172
- diff ( props ) {
182
+ diff ( props : any ) {
173
183
this . props = { ...this . props , ...props }
174
184
let {
175
185
from = { } ,
@@ -179,7 +189,6 @@ export default class Controller {
179
189
attach,
180
190
reset,
181
191
immediate,
182
- ref,
183
192
} = this . props
184
193
185
194
// Reverse values when requested
@@ -195,8 +204,8 @@ export default class Controller {
195
204
let target = attach && attach ( this )
196
205
197
206
// Reduces input { name: value } pairs into animated values
198
- this . animations = Object . entries ( this . merged ) . reduce (
199
- ( acc , [ name , value ] , i ) => {
207
+ this . animations = Object . entries < any > ( this . merged ) . reduce (
208
+ ( acc , [ name , value ] ) => {
200
209
// Issue cached entries, except on reset
201
210
let entry = acc [ name ] || { }
202
211
@@ -222,12 +231,16 @@ export default class Controller {
222
231
223
232
let newValue = value
224
233
if ( isInterpolation )
225
- newValue = interp ( { range : [ 0 , 1 ] , output : [ value , value ] } ) ( 1 )
234
+ newValue = interp ( {
235
+ range : [ 0 , 1 ] ,
236
+ output : [ value as string , value as string ] ,
237
+ } ) ( 1 )
226
238
let currentValue = interpolation && interpolation . getValue ( )
227
239
228
240
// Change detection flags
229
241
const isFirst = is . und ( parent )
230
- const isActive = ! isFirst && entry . animatedValues . some ( v => ! v . done )
242
+ const isActive =
243
+ ! isFirst && entry . animatedValues . some ( ( v : AnimatedValue ) => ! v . done )
231
244
const currentValueDiffersFromGoal = ! is . equ ( newValue , currentValue )
232
245
const hasNewGoal = ! is . equ ( newValue , entry . previous )
233
246
const hasNewConfig = ! is . equ ( toConfig , entry . config )
@@ -301,7 +314,7 @@ export default class Controller {
301
314
friction : withDefault ( toConfig . friction , 26 ) ,
302
315
mass : withDefault ( toConfig . mass , 1 ) ,
303
316
duration : toConfig . duration ,
304
- easing : withDefault ( toConfig . easing , t => t ) ,
317
+ easing : withDefault ( toConfig . easing , ( t : number ) => t ) ,
305
318
decay : toConfig . decay ,
306
319
} ,
307
320
}
@@ -329,8 +342,8 @@ export default class Controller {
329
342
if ( this . hasChanged ) {
330
343
// Make animations available to frameloop
331
344
this . configs = Object . values ( this . animations )
332
- this . values = { }
333
- this . interpolations = { }
345
+ this . values = { } as ValuesFor < P >
346
+ this . interpolations = { } as InterpolationsFor < P >
334
347
for ( let key in this . animations ) {
335
348
this . interpolations [ key ] = this . animations [ key ] . interpolation
336
349
this . values [ key ] = this . animations [ key ] . interpolation . getValue ( )
@@ -341,14 +354,16 @@ export default class Controller {
341
354
342
355
destroy ( ) {
343
356
this . stop ( )
344
- this . props = { }
357
+ this . props = { } as P
345
358
this . merged = { }
346
- this . animations = { }
347
- this . interpolations = { }
348
- this . values = { }
359
+ this . animations = { } as AnimationsFor < P >
360
+ this . interpolations = { } as InterpolationsFor < P >
361
+ this . values = { } as ValuesFor < P >
349
362
this . configs = [ ]
350
363
this . local = 0
351
364
}
352
365
353
366
getValues = ( ) => this . interpolations
354
367
}
368
+
369
+ export default Controller
0 commit comments