@angular/animations 21.0.0-next.8 → 21.0.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,1205 +1,335 @@
1
1
  /**
2
- * @license Angular v21.0.0-next.8
2
+ * @license Angular v21.0.0-rc.0
3
3
  * (c) 2010-2025 Google LLC. https://angular.dev/
4
4
  * License: MIT
5
5
  */
6
6
 
7
- /**
8
- * @description Constants for the categories of parameters that can be defined for animations.
9
- *
10
- * A corresponding function defines a set of parameters for each category, and
11
- * collects them into a corresponding `AnimationMetadata` object.
12
- *
13
- * @publicApi
14
- *
15
- * @deprecated 20.2 Use `animate.enter` or `animate.leave` instead. Intent to remove in v23
16
- */
17
7
  var AnimationMetadataType;
18
8
  (function (AnimationMetadataType) {
19
- /**
20
- * Associates a named animation state with a set of CSS styles.
21
- * See [`state()`](api/animations/state)
22
- */
23
- AnimationMetadataType[AnimationMetadataType["State"] = 0] = "State";
24
- /**
25
- * Data for a transition from one animation state to another.
26
- * See `transition()`
27
- */
28
- AnimationMetadataType[AnimationMetadataType["Transition"] = 1] = "Transition";
29
- /**
30
- * Contains a set of animation steps.
31
- * See `sequence()`
32
- */
33
- AnimationMetadataType[AnimationMetadataType["Sequence"] = 2] = "Sequence";
34
- /**
35
- * Contains a set of animation steps.
36
- * See `group()`
37
- */
38
- AnimationMetadataType[AnimationMetadataType["Group"] = 3] = "Group";
39
- /**
40
- * Contains an animation step.
41
- * See `animate()`
42
- */
43
- AnimationMetadataType[AnimationMetadataType["Animate"] = 4] = "Animate";
44
- /**
45
- * Contains a set of animation steps.
46
- * See `keyframes()`
47
- */
48
- AnimationMetadataType[AnimationMetadataType["Keyframes"] = 5] = "Keyframes";
49
- /**
50
- * Contains a set of CSS property-value pairs into a named style.
51
- * See `style()`
52
- */
53
- AnimationMetadataType[AnimationMetadataType["Style"] = 6] = "Style";
54
- /**
55
- * Associates an animation with an entry trigger that can be attached to an element.
56
- * See `trigger()`
57
- */
58
- AnimationMetadataType[AnimationMetadataType["Trigger"] = 7] = "Trigger";
59
- /**
60
- * Contains a re-usable animation.
61
- * See `animation()`
62
- */
63
- AnimationMetadataType[AnimationMetadataType["Reference"] = 8] = "Reference";
64
- /**
65
- * Contains data to use in executing child animations returned by a query.
66
- * See `animateChild()`
67
- */
68
- AnimationMetadataType[AnimationMetadataType["AnimateChild"] = 9] = "AnimateChild";
69
- /**
70
- * Contains animation parameters for a re-usable animation.
71
- * See `useAnimation()`
72
- */
73
- AnimationMetadataType[AnimationMetadataType["AnimateRef"] = 10] = "AnimateRef";
74
- /**
75
- * Contains child-animation query data.
76
- * See `query()`
77
- */
78
- AnimationMetadataType[AnimationMetadataType["Query"] = 11] = "Query";
79
- /**
80
- * Contains data for staggering an animation sequence.
81
- * See `stagger()`
82
- */
83
- AnimationMetadataType[AnimationMetadataType["Stagger"] = 12] = "Stagger";
9
+ AnimationMetadataType[AnimationMetadataType["State"] = 0] = "State";
10
+ AnimationMetadataType[AnimationMetadataType["Transition"] = 1] = "Transition";
11
+ AnimationMetadataType[AnimationMetadataType["Sequence"] = 2] = "Sequence";
12
+ AnimationMetadataType[AnimationMetadataType["Group"] = 3] = "Group";
13
+ AnimationMetadataType[AnimationMetadataType["Animate"] = 4] = "Animate";
14
+ AnimationMetadataType[AnimationMetadataType["Keyframes"] = 5] = "Keyframes";
15
+ AnimationMetadataType[AnimationMetadataType["Style"] = 6] = "Style";
16
+ AnimationMetadataType[AnimationMetadataType["Trigger"] = 7] = "Trigger";
17
+ AnimationMetadataType[AnimationMetadataType["Reference"] = 8] = "Reference";
18
+ AnimationMetadataType[AnimationMetadataType["AnimateChild"] = 9] = "AnimateChild";
19
+ AnimationMetadataType[AnimationMetadataType["AnimateRef"] = 10] = "AnimateRef";
20
+ AnimationMetadataType[AnimationMetadataType["Query"] = 11] = "Query";
21
+ AnimationMetadataType[AnimationMetadataType["Stagger"] = 12] = "Stagger";
84
22
  })(AnimationMetadataType || (AnimationMetadataType = {}));
85
- /**
86
- * Specifies automatic styling.
87
- *
88
- * @publicApi
89
- *
90
- * @deprecated 20.2 Use `animate.enter` or `animate.leave` instead. Intent to remove in v23
91
- */
92
23
  const AUTO_STYLE = '*';
93
- /**
94
- * Creates a named animation trigger, containing a list of [`state()`](api/animations/state)
95
- * and `transition()` entries to be evaluated when the expression
96
- * bound to the trigger changes.
97
- *
98
- * @param name An identifying string.
99
- * @param definitions An animation definition object, containing an array of
100
- * [`state()`](api/animations/state) and `transition()` declarations.
101
- *
102
- * @return An object that encapsulates the trigger data.
103
- *
104
- * @usageNotes
105
- * Define an animation trigger in the `animations` section of `@Component` metadata.
106
- * In the template, reference the trigger by name and bind it to a trigger expression that
107
- * evaluates to a defined animation state, using the following format:
108
- *
109
- * `[@triggerName]="expression"`
110
- *
111
- * Animation trigger bindings convert all values to strings, and then match the
112
- * previous and current values against any linked transitions.
113
- * Booleans can be specified as `1` or `true` and `0` or `false`.
114
- *
115
- * ### Usage Example
116
- *
117
- * The following example creates an animation trigger reference based on the provided
118
- * name value.
119
- * The provided animation value is expected to be an array consisting of state and
120
- * transition declarations.
121
- *
122
- * ```ts
123
- * @Component({
124
- * selector: "my-component",
125
- * templateUrl: "my-component-tpl.html",
126
- * animations: [
127
- * trigger("myAnimationTrigger", [
128
- * state(...),
129
- * state(...),
130
- * transition(...),
131
- * transition(...)
132
- * ])
133
- * ]
134
- * })
135
- * class MyComponent {
136
- * myStatusExp = "something";
137
- * }
138
- * ```
139
- *
140
- * The template associated with this component makes use of the defined trigger
141
- * by binding to an element within its template code.
142
- *
143
- * ```html
144
- * <!-- somewhere inside of my-component-tpl.html -->
145
- * <div [@myAnimationTrigger]="myStatusExp">...</div>
146
- * ```
147
- *
148
- * ### Using an inline function
149
- * The `transition` animation method also supports reading an inline function which can decide
150
- * if its associated animation should be run.
151
- *
152
- * ```ts
153
- * // this method is run each time the `myAnimationTrigger` trigger value changes.
154
- * function myInlineMatcherFn(fromState: string, toState: string, element: any, params: {[key:
155
- string]: any}): boolean {
156
- * // notice that `element` and `params` are also available here
157
- * return toState == 'yes-please-animate';
158
- * }
159
- *
160
- * @Component({
161
- * selector: 'my-component',
162
- * templateUrl: 'my-component-tpl.html',
163
- * animations: [
164
- * trigger('myAnimationTrigger', [
165
- * transition(myInlineMatcherFn, [
166
- * // the animation sequence code
167
- * ]),
168
- * ])
169
- * ]
170
- * })
171
- * class MyComponent {
172
- * myStatusExp = "yes-please-animate";
173
- * }
174
- * ```
175
- *
176
- * ### Disabling Animations
177
- * When true, the special animation control binding `@.disabled` binding prevents
178
- * all animations from rendering.
179
- * Place the `@.disabled` binding on an element to disable
180
- * animations on the element itself, as well as any inner animation triggers
181
- * within the element.
182
- *
183
- * The following example shows how to use this feature:
184
- *
185
- * ```angular-ts
186
- * @Component({
187
- * selector: 'my-component',
188
- * template: `
189
- * <div [@.disabled]="isDisabled">
190
- * <div [@childAnimation]="exp"></div>
191
- * </div>
192
- * `,
193
- * animations: [
194
- * trigger("childAnimation", [
195
- * // ...
196
- * ])
197
- * ]
198
- * })
199
- * class MyComponent {
200
- * isDisabled = true;
201
- * exp = '...';
202
- * }
203
- * ```
204
- *
205
- * When `@.disabled` is true, it prevents the `@childAnimation` trigger from animating,
206
- * along with any inner animations.
207
- *
208
- * ### Disable animations application-wide
209
- * When an area of the template is set to have animations disabled,
210
- * **all** inner components have their animations disabled as well.
211
- * This means that you can disable all animations for an app
212
- * by placing a host binding set on `@.disabled` on the topmost Angular component.
213
- *
214
- * ```ts
215
- * import {Component, HostBinding} from '@angular/core';
216
- *
217
- * @Component({
218
- * selector: 'app-component',
219
- * templateUrl: 'app.component.html',
220
- * })
221
- * class AppComponent {
222
- * @HostBinding('@.disabled')
223
- * public animationsDisabled = true;
224
- * }
225
- * ```
226
- *
227
- * ### Overriding disablement of inner animations
228
- * Despite inner animations being disabled, a parent animation can `query()`
229
- * for inner elements located in disabled areas of the template and still animate
230
- * them if needed. This is also the case for when a sub animation is
231
- * queried by a parent and then later animated using `animateChild()`.
232
- *
233
- * ### Detecting when an animation is disabled
234
- * If a region of the DOM (or the entire application) has its animations disabled, the animation
235
- * trigger callbacks still fire, but for zero seconds. When the callback fires, it provides
236
- * an instance of an `AnimationEvent`. If animations are disabled,
237
- * the `.disabled` flag on the event is true.
238
- *
239
- * @publicApi
240
- *
241
- * @deprecated 20.2 Use `animate.enter` or `animate.leave` instead. Intent to remove in v23
242
- */
243
24
  function trigger(name, definitions) {
244
- return { type: AnimationMetadataType.Trigger, name, definitions, options: {} };
25
+ return {
26
+ type: AnimationMetadataType.Trigger,
27
+ name,
28
+ definitions,
29
+ options: {}
30
+ };
245
31
  }
246
- /**
247
- * Defines an animation step that combines styling information with timing information.
248
- *
249
- * @param timings Sets `AnimateTimings` for the parent animation.
250
- * A string in the format "duration [delay] [easing]".
251
- * - Duration and delay are expressed as a number and optional time unit,
252
- * such as "1s" or "10ms" for one second and 10 milliseconds, respectively.
253
- * The default unit is milliseconds.
254
- * - The easing value controls how the animation accelerates and decelerates
255
- * during its runtime. Value is one of `ease`, `ease-in`, `ease-out`,
256
- * `ease-in-out`, or a `cubic-bezier()` function call.
257
- * If not supplied, no easing is applied.
258
- *
259
- * For example, the string "1s 100ms ease-out" specifies a duration of
260
- * 1000 milliseconds, and delay of 100 ms, and the "ease-out" easing style,
261
- * which decelerates near the end of the duration.
262
- * @param styles Sets AnimationStyles for the parent animation.
263
- * A function call to either `style()` or `keyframes()`
264
- * that returns a collection of CSS style entries to be applied to the parent animation.
265
- * When null, uses the styles from the destination state.
266
- * This is useful when describing an animation step that will complete an animation;
267
- * see "Animating to the final state" in `transitions()`.
268
- * @returns An object that encapsulates the animation step.
269
- *
270
- * @usageNotes
271
- * Call within an animation `sequence()`, {@link /api/animations/group group()}, or
272
- * `transition()` call to specify an animation step
273
- * that applies given style data to the parent animation for a given amount of time.
274
- *
275
- * ### Syntax Examples
276
- * **Timing examples**
277
- *
278
- * The following examples show various `timings` specifications.
279
- * - `animate(500)` : Duration is 500 milliseconds.
280
- * - `animate("1s")` : Duration is 1000 milliseconds.
281
- * - `animate("100ms 0.5s")` : Duration is 100 milliseconds, delay is 500 milliseconds.
282
- * - `animate("5s ease-in")` : Duration is 5000 milliseconds, easing in.
283
- * - `animate("5s 10ms cubic-bezier(.17,.67,.88,.1)")` : Duration is 5000 milliseconds, delay is 10
284
- * milliseconds, easing according to a bezier curve.
285
- *
286
- * **Style examples**
287
- *
288
- * The following example calls `style()` to set a single CSS style.
289
- * ```ts
290
- * animate(500, style({ background: "red" }))
291
- * ```
292
- * The following example calls `keyframes()` to set a CSS style
293
- * to different values for successive keyframes.
294
- * ```ts
295
- * animate(500, keyframes(
296
- * [
297
- * style({ background: "blue" }),
298
- * style({ background: "red" })
299
- * ])
300
- * ```
301
- *
302
- * @publicApi
303
- *
304
- * @deprecated 20.2 Use `animate.enter` or `animate.leave` instead. Intent to remove in v23
305
- */
306
32
  function animate(timings, styles = null) {
307
- return { type: AnimationMetadataType.Animate, styles, timings };
33
+ return {
34
+ type: AnimationMetadataType.Animate,
35
+ styles,
36
+ timings
37
+ };
308
38
  }
309
- /**
310
- * @description Defines a list of animation steps to be run in parallel.
311
- *
312
- * @param steps An array of animation step objects.
313
- * - When steps are defined by `style()` or `animate()`
314
- * function calls, each call within the group is executed instantly.
315
- * - To specify offset styles to be applied at a later time, define steps with
316
- * `keyframes()`, or use `animate()` calls with a delay value.
317
- * For example:
318
- *
319
- * ```ts
320
- * group([
321
- * animate("1s", style({ background: "black" })),
322
- * animate("2s", style({ color: "white" }))
323
- * ])
324
- * ```
325
- *
326
- * @param options An options object containing a delay and
327
- * developer-defined parameters that provide styling defaults and
328
- * can be overridden on invocation.
329
- *
330
- * @return An object that encapsulates the group data.
331
- *
332
- * @usageNotes
333
- * Grouped animations are useful when a series of styles must be
334
- * animated at different starting times and closed off at different ending times.
335
- *
336
- * When called within a `sequence()` or a
337
- * `transition()` call, does not continue to the next
338
- * instruction until all of the inner animation steps have completed.
339
- *
340
- * @publicApi
341
- *
342
- * @deprecated 20.2 Use `animate.enter` or `animate.leave` instead. Intent to remove in v23
343
- */
344
39
  function group(steps, options = null) {
345
- return { type: AnimationMetadataType.Group, steps, options };
40
+ return {
41
+ type: AnimationMetadataType.Group,
42
+ steps,
43
+ options
44
+ };
346
45
  }
347
- /**
348
- * Defines a list of animation steps to be run sequentially, one by one.
349
- *
350
- * @param steps An array of animation step objects.
351
- * - Steps defined by `style()` calls apply the styling data immediately.
352
- * - Steps defined by `animate()` calls apply the styling data over time
353
- * as specified by the timing data.
354
- *
355
- * ```ts
356
- * sequence([
357
- * style({ opacity: 0 }),
358
- * animate("1s", style({ opacity: 1 }))
359
- * ])
360
- * ```
361
- *
362
- * @param options An options object containing a delay and
363
- * developer-defined parameters that provide styling defaults and
364
- * can be overridden on invocation.
365
- *
366
- * @return An object that encapsulates the sequence data.
367
- *
368
- * @usageNotes
369
- * When you pass an array of steps to a
370
- * `transition()` call, the steps run sequentially by default.
371
- * Compare this to the {@link /api/animations/group group()} call, which runs animation steps in
372
- *parallel.
373
- *
374
- * When a sequence is used within a {@link /api/animations/group group()} or a `transition()` call,
375
- * execution continues to the next instruction only after each of the inner animation
376
- * steps have completed.
377
- *
378
- * @publicApi
379
- *
380
- * @deprecated 20.2 Use `animate.enter` or `animate.leave` instead. Intent to remove in v23
381
- **/
382
46
  function sequence(steps, options = null) {
383
- return { type: AnimationMetadataType.Sequence, steps, options };
47
+ return {
48
+ type: AnimationMetadataType.Sequence,
49
+ steps,
50
+ options
51
+ };
384
52
  }
385
- /**
386
- * Declares a key/value object containing CSS properties/styles that
387
- * can then be used for an animation [`state`](api/animations/state), within an animation
388
- *`sequence`, or as styling data for calls to `animate()` and `keyframes()`.
389
- *
390
- * @param tokens A set of CSS styles or HTML styles associated with an animation state.
391
- * The value can be any of the following:
392
- * - A key-value style pair associating a CSS property with a value.
393
- * - An array of key-value style pairs.
394
- * - An asterisk (*), to use auto-styling, where styles are derived from the element
395
- * being animated and applied to the animation when it starts.
396
- *
397
- * Auto-styling can be used to define a state that depends on layout or other
398
- * environmental factors.
399
- *
400
- * @return An object that encapsulates the style data.
401
- *
402
- * @usageNotes
403
- * The following examples create animation styles that collect a set of
404
- * CSS property values:
405
- *
406
- * ```ts
407
- * // string values for CSS properties
408
- * style({ background: "red", color: "blue" })
409
- *
410
- * // numerical pixel values
411
- * style({ width: 100, height: 0 })
412
- * ```
413
- *
414
- * The following example uses auto-styling to allow an element to animate from
415
- * a height of 0 up to its full height:
416
- *
417
- * ```ts
418
- * style({ height: 0 }),
419
- * animate("1s", style({ height: "*" }))
420
- * ```
421
- *
422
- * @publicApi
423
- *
424
- * @deprecated 20.2 Use `animate.enter` or `animate.leave` instead. Intent to remove in v23
425
- **/
426
53
  function style(tokens) {
427
- return { type: AnimationMetadataType.Style, styles: tokens, offset: null };
54
+ return {
55
+ type: AnimationMetadataType.Style,
56
+ styles: tokens,
57
+ offset: null
58
+ };
428
59
  }
429
- /**
430
- * Declares an animation state within a trigger attached to an element.
431
- *
432
- * @param name One or more names for the defined state in a comma-separated string.
433
- * The following reserved state names can be supplied to define a style for specific use
434
- * cases:
435
- *
436
- * - `void` You can associate styles with this name to be used when
437
- * the element is detached from the application. For example, when an `ngIf` evaluates
438
- * to false, the state of the associated element is void.
439
- * - `*` (asterisk) Indicates the default state. You can associate styles with this name
440
- * to be used as the fallback when the state that is being animated is not declared
441
- * within the trigger.
442
- *
443
- * @param styles A set of CSS styles associated with this state, created using the
444
- * `style()` function.
445
- * This set of styles persists on the element once the state has been reached.
446
- * @param options Parameters that can be passed to the state when it is invoked.
447
- * 0 or more key-value pairs.
448
- * @return An object that encapsulates the new state data.
449
- *
450
- * @usageNotes
451
- * Use the `trigger()` function to register states to an animation trigger.
452
- * Use the `transition()` function to animate between states.
453
- * When a state is active within a component, its associated styles persist on the element,
454
- * even when the animation ends.
455
- *
456
- * @publicApi
457
- *
458
- * @deprecated 20.2 Use `animate.enter` or `animate.leave` instead. Intent to remove in v23
459
- **/
460
60
  function state(name, styles, options) {
461
- return { type: AnimationMetadataType.State, name, styles, options };
61
+ return {
62
+ type: AnimationMetadataType.State,
63
+ name,
64
+ styles,
65
+ options
66
+ };
462
67
  }
463
- /**
464
- * Defines a set of animation styles, associating each style with an optional `offset` value.
465
- *
466
- * @param steps A set of animation styles with optional offset data.
467
- * The optional `offset` value for a style specifies a percentage of the total animation
468
- * time at which that style is applied.
469
- * @returns An object that encapsulates the keyframes data.
470
- *
471
- * @usageNotes
472
- * Use with the `animate()` call. Instead of applying animations
473
- * from the current state
474
- * to the destination state, keyframes describe how each style entry is applied and at what point
475
- * within the animation arc.
476
- * Compare [CSS Keyframe Animations](https://www.w3schools.com/css/css3_animations.asp).
477
- *
478
- * ### Usage
479
- *
480
- * In the following example, the offset values describe
481
- * when each `backgroundColor` value is applied. The color is red at the start, and changes to
482
- * blue when 20% of the total time has elapsed.
483
- *
484
- * ```ts
485
- * // the provided offset values
486
- * animate("5s", keyframes([
487
- * style({ backgroundColor: "red", offset: 0 }),
488
- * style({ backgroundColor: "blue", offset: 0.2 }),
489
- * style({ backgroundColor: "orange", offset: 0.3 }),
490
- * style({ backgroundColor: "black", offset: 1 })
491
- * ]))
492
- * ```
493
- *
494
- * If there are no `offset` values specified in the style entries, the offsets
495
- * are calculated automatically.
496
- *
497
- * ```ts
498
- * animate("5s", keyframes([
499
- * style({ backgroundColor: "red" }) // offset = 0
500
- * style({ backgroundColor: "blue" }) // offset = 0.33
501
- * style({ backgroundColor: "orange" }) // offset = 0.66
502
- * style({ backgroundColor: "black" }) // offset = 1
503
- * ]))
504
- *```
505
-
506
- * @publicApi
507
- *
508
- * @deprecated 20.2 Use `animate.enter` or `animate.leave` instead. Intent to remove in v23
509
- */
510
68
  function keyframes(steps) {
511
- return { type: AnimationMetadataType.Keyframes, steps };
69
+ return {
70
+ type: AnimationMetadataType.Keyframes,
71
+ steps
72
+ };
512
73
  }
513
- /**
514
- * Declares an animation transition which is played when a certain specified condition is met.
515
- *
516
- * @param stateChangeExpr A string with a specific format or a function that specifies when the
517
- * animation transition should occur (see [State Change Expression](#state-change-expression)).
518
- *
519
- * @param steps One or more animation objects that represent the animation's instructions.
520
- *
521
- * @param options An options object that can be used to specify a delay for the animation or provide
522
- * custom parameters for it.
523
- *
524
- * @returns An object that encapsulates the transition data.
525
- *
526
- * @usageNotes
527
- *
528
- * ### State Change Expression
529
- *
530
- * The State Change Expression instructs Angular when to run the transition's animations, it can
531
- *either be
532
- * - a string with a specific syntax
533
- * - or a function that compares the previous and current state (value of the expression bound to
534
- * the element's trigger) and returns `true` if the transition should occur or `false` otherwise
535
- *
536
- * The string format can be:
537
- * - `fromState => toState`, which indicates that the transition's animations should occur then the
538
- * expression bound to the trigger's element goes from `fromState` to `toState`
539
- *
540
- * _Example:_
541
- * ```ts
542
- * transition('open => closed', animate('.5s ease-out', style({ height: 0 }) ))
543
- * ```
544
- *
545
- * - `fromState <=> toState`, which indicates that the transition's animations should occur then
546
- * the expression bound to the trigger's element goes from `fromState` to `toState` or vice versa
547
- *
548
- * _Example:_
549
- * ```ts
550
- * transition('enabled <=> disabled', animate('1s cubic-bezier(0.8,0.3,0,1)'))
551
- * ```
552
- *
553
- * - `:enter`/`:leave`, which indicates that the transition's animations should occur when the
554
- * element enters or exists the DOM
555
- *
556
- * _Example:_
557
- * ```ts
558
- * transition(':enter', [
559
- * style({ opacity: 0 }),
560
- * animate('500ms', style({ opacity: 1 }))
561
- * ])
562
- * ```
563
- *
564
- * - `:increment`/`:decrement`, which indicates that the transition's animations should occur when
565
- * the numerical expression bound to the trigger's element has increased in value or decreased
566
- *
567
- * _Example:_
568
- * ```ts
569
- * transition(':increment', query('@counter', animateChild()))
570
- * ```
571
- *
572
- * - a sequence of any of the above divided by commas, which indicates that transition's animations
573
- * should occur whenever one of the state change expressions matches
574
- *
575
- * _Example:_
576
- * ```ts
577
- * transition(':increment, * => enabled, :enter', animate('1s ease', keyframes([
578
- * style({ transform: 'scale(1)', offset: 0}),
579
- * style({ transform: 'scale(1.1)', offset: 0.7}),
580
- * style({ transform: 'scale(1)', offset: 1})
581
- * ]))),
582
- * ```
583
- *
584
- * Also note that in such context:
585
- * - `void` can be used to indicate the absence of the element
586
- * - asterisks can be used as wildcards that match any state
587
- * - (as a consequence of the above, `void => *` is equivalent to `:enter` and `* => void` is
588
- * equivalent to `:leave`)
589
- * - `true` and `false` also match expression values of `1` and `0` respectively (but do not match
590
- * _truthy_ and _falsy_ values)
591
- *
592
- * <div class="docs-alert docs-alert-helpful">
593
- *
594
- * Be careful about entering end leaving elements as their transitions present a common
595
- * pitfall for developers.
596
- *
597
- * Note that when an element with a trigger enters the DOM its `:enter` transition always
598
- * gets executed, but its `:leave` transition will not be executed if the element is removed
599
- * alongside its parent (as it will be removed "without warning" before its transition has
600
- * a chance to be executed, the only way that such transition can occur is if the element
601
- * is exiting the DOM on its own).
602
- *
603
- *
604
- * </div>
605
- *
606
- * ### Animating to a Final State
607
- *
608
- * If the final step in a transition is a call to `animate()` that uses a timing value
609
- * with no `style` data, that step is automatically considered the final animation arc,
610
- * for the element to reach the final state, in such case Angular automatically adds or removes
611
- * CSS styles to ensure that the element is in the correct final state.
612
- *
613
- *
614
- * ### Usage Examples
615
- *
616
- * - Transition animations applied based on
617
- * the trigger's expression value
618
- *
619
- * ```html
620
- * <div [@myAnimationTrigger]="myStatusExp">
621
- * ...
622
- * </div>
623
- * ```
624
- *
625
- * ```ts
626
- * trigger("myAnimationTrigger", [
627
- * ..., // states
628
- * transition("on => off, open => closed", animate(500)),
629
- * transition("* <=> error", query('.indicator', animateChild()))
630
- * ])
631
- * ```
632
- *
633
- * - Transition animations applied based on custom logic dependent
634
- * on the trigger's expression value and provided parameters
635
- *
636
- * ```html
637
- * <div [@myAnimationTrigger]="{
638
- * value: stepName,
639
- * params: { target: currentTarget }
640
- * }">
641
- * ...
642
- * </div>
643
- * ```
644
- *
645
- * ```ts
646
- * trigger("myAnimationTrigger", [
647
- * ..., // states
648
- * transition(
649
- * (fromState, toState, _element, params) =>
650
- * ['firststep', 'laststep'].includes(fromState.toLowerCase())
651
- * && toState === params?.['target'],
652
- * animate('1s')
653
- * )
654
- * ])
655
- * ```
656
- *
657
- * @publicApi
658
- *
659
- * @deprecated 20.2 Use `animate.enter` or `animate.leave` instead. Intent to remove in v23
660
- **/
661
74
  function transition(stateChangeExpr, steps, options = null) {
662
- return { type: AnimationMetadataType.Transition, expr: stateChangeExpr, animation: steps, options };
75
+ return {
76
+ type: AnimationMetadataType.Transition,
77
+ expr: stateChangeExpr,
78
+ animation: steps,
79
+ options
80
+ };
663
81
  }
664
- /**
665
- * Produces a reusable animation that can be invoked in another animation or sequence,
666
- * by calling the `useAnimation()` function.
667
- *
668
- * @param steps One or more animation objects, as returned by the `animate()`
669
- * or `sequence()` function, that form a transformation from one state to another.
670
- * A sequence is used by default when you pass an array.
671
- * @param options An options object that can contain a delay value for the start of the
672
- * animation, and additional developer-defined parameters.
673
- * Provided values for additional parameters are used as defaults,
674
- * and override values can be passed to the caller on invocation.
675
- * @returns An object that encapsulates the animation data.
676
- *
677
- * @usageNotes
678
- * The following example defines a reusable animation, providing some default parameter
679
- * values.
680
- *
681
- * ```ts
682
- * var fadeAnimation = animation([
683
- * style({ opacity: '{{ start }}' }),
684
- * animate('{{ time }}',
685
- * style({ opacity: '{{ end }}'}))
686
- * ],
687
- * { params: { time: '1000ms', start: 0, end: 1 }});
688
- * ```
689
- *
690
- * The following invokes the defined animation with a call to `useAnimation()`,
691
- * passing in override parameter values.
692
- *
693
- * ```js
694
- * useAnimation(fadeAnimation, {
695
- * params: {
696
- * time: '2s',
697
- * start: 1,
698
- * end: 0
699
- * }
700
- * })
701
- * ```
702
- *
703
- * If any of the passed-in parameter values are missing from this call,
704
- * the default values are used. If one or more parameter values are missing before a step is
705
- * animated, `useAnimation()` throws an error.
706
- *
707
- * @publicApi
708
- *
709
- * @deprecated 20.2 Use `animate.enter` or `animate.leave` instead. Intent to remove in v23
710
- */
711
82
  function animation(steps, options = null) {
712
- return { type: AnimationMetadataType.Reference, animation: steps, options };
83
+ return {
84
+ type: AnimationMetadataType.Reference,
85
+ animation: steps,
86
+ options
87
+ };
713
88
  }
714
- /**
715
- * Executes a queried inner animation element within an animation sequence.
716
- *
717
- * @param options An options object that can contain a delay value for the start of the
718
- * animation, and additional override values for developer-defined parameters.
719
- * @return An object that encapsulates the child animation data.
720
- *
721
- * @usageNotes
722
- * Each time an animation is triggered in Angular, the parent animation
723
- * has priority and any child animations are blocked. In order
724
- * for a child animation to run, the parent animation must query each of the elements
725
- * containing child animations, and run them using this function.
726
- *
727
- * Note that this feature is designed to be used with `query()` and it will only work
728
- * with animations that are assigned using the Angular animation library. CSS keyframes
729
- * and transitions are not handled by this API.
730
- *
731
- * @publicApi
732
- *
733
- * @deprecated 20.2 Use `animate.enter` or `animate.leave` instead. Intent to remove in v23
734
- */
735
89
  function animateChild(options = null) {
736
- return { type: AnimationMetadataType.AnimateChild, options };
90
+ return {
91
+ type: AnimationMetadataType.AnimateChild,
92
+ options
93
+ };
737
94
  }
738
- /**
739
- * Starts a reusable animation that is created using the `animation()` function.
740
- *
741
- * @param animation The reusable animation to start.
742
- * @param options An options object that can contain a delay value for the start of
743
- * the animation, and additional override values for developer-defined parameters.
744
- * @return An object that contains the animation parameters.
745
- *
746
- * @publicApi
747
- *
748
- * @deprecated 20.2 Use `animate.enter` or `animate.leave` instead. Intent to remove in v23
749
- */
750
95
  function useAnimation(animation, options = null) {
751
- return { type: AnimationMetadataType.AnimateRef, animation, options };
96
+ return {
97
+ type: AnimationMetadataType.AnimateRef,
98
+ animation,
99
+ options
100
+ };
752
101
  }
753
- /**
754
- * Finds one or more inner elements within the current element that is
755
- * being animated within a sequence. Use with `animate()`.
756
- *
757
- * @param selector The element to query, or a set of elements that contain Angular-specific
758
- * characteristics, specified with one or more of the following tokens.
759
- * - `query(":enter")` or `query(":leave")` : Query for newly inserted/removed elements (not
760
- * all elements can be queried via these tokens, see
761
- * [Entering and Leaving Elements](#entering-and-leaving-elements))
762
- * - `query(":animating")` : Query all currently animating elements.
763
- * - `query("@triggerName")` : Query elements that contain an animation trigger.
764
- * - `query("@*")` : Query all elements that contain an animation triggers.
765
- * - `query(":self")` : Include the current element into the animation sequence.
766
- *
767
- * @param animation One or more animation steps to apply to the queried element or elements.
768
- * An array is treated as an animation sequence.
769
- * @param options An options object. Use the 'limit' field to limit the total number of
770
- * items to collect.
771
- * @return An object that encapsulates the query data.
772
- *
773
- * @usageNotes
774
- *
775
- * ### Multiple Tokens
776
- *
777
- * Tokens can be merged into a combined query selector string. For example:
778
- *
779
- * ```ts
780
- * query(':self, .record:enter, .record:leave, @subTrigger', [...])
781
- * ```
782
- *
783
- * The `query()` function collects multiple elements and works internally by using
784
- * `element.querySelectorAll`. Use the `limit` field of an options object to limit
785
- * the total number of items to be collected. For example:
786
- *
787
- * ```js
788
- * query('div', [
789
- * animate(...),
790
- * animate(...)
791
- * ], { limit: 1 })
792
- * ```
793
- *
794
- * By default, throws an error when zero items are found. Set the
795
- * `optional` flag to ignore this error. For example:
796
- *
797
- * ```js
798
- * query('.some-element-that-may-not-be-there', [
799
- * animate(...),
800
- * animate(...)
801
- * ], { optional: true })
802
- * ```
803
- *
804
- * ### Entering and Leaving Elements
805
- *
806
- * Not all elements can be queried via the `:enter` and `:leave` tokens, the only ones
807
- * that can are those that Angular assumes can enter/leave based on their own logic
808
- * (if their insertion/removal is simply a consequence of that of their parent they
809
- * should be queried via a different token in their parent's `:enter`/`:leave` transitions).
810
- *
811
- * The only elements Angular assumes can enter/leave based on their own logic (thus the only
812
- * ones that can be queried via the `:enter` and `:leave` tokens) are:
813
- * - Those inserted dynamically (via `ViewContainerRef`)
814
- * - Those that have a structural directive (which, under the hood, are a subset of the above ones)
815
- *
816
- * <div class="docs-alert docs-alert-helpful">
817
- *
818
- * Note that elements will be successfully queried via `:enter`/`:leave` even if their
819
- * insertion/removal is not done manually via `ViewContainerRef`or caused by their structural
820
- * directive (e.g. they enter/exit alongside their parent).
821
- *
822
- * </div>
823
- *
824
- * <div class="docs-alert docs-alert-important">
825
- *
826
- * There is an exception to what previously mentioned, besides elements entering/leaving based on
827
- * their own logic, elements with an animation trigger can always be queried via `:leave` when
828
- * their parent is also leaving.
829
- *
830
- * </div>
831
- *
832
- * ### Usage Example
833
- *
834
- * The following example queries for inner elements and animates them
835
- * individually using `animate()`.
836
- *
837
- * ```angular-ts
838
- * @Component({
839
- * selector: 'inner',
840
- * template: `
841
- * <div [@queryAnimation]="exp">
842
- * <h1>Title</h1>
843
- * <div class="content">
844
- * Blah blah blah
845
- * </div>
846
- * </div>
847
- * `,
848
- * animations: [
849
- * trigger('queryAnimation', [
850
- * transition('* => goAnimate', [
851
- * // hide the inner elements
852
- * query('h1', style({ opacity: 0 })),
853
- * query('.content', style({ opacity: 0 })),
854
- *
855
- * // animate the inner elements in, one by one
856
- * query('h1', animate(1000, style({ opacity: 1 }))),
857
- * query('.content', animate(1000, style({ opacity: 1 }))),
858
- * ])
859
- * ])
860
- * ]
861
- * })
862
- * class Cmp {
863
- * exp = '';
864
- *
865
- * goAnimate() {
866
- * this.exp = 'goAnimate';
867
- * }
868
- * }
869
- * ```
870
- *
871
- * @publicApi
872
- *
873
- * @deprecated 20.2 Use `animate.enter` or `animate.leave` instead. Intent to remove in v23
874
- */
875
102
  function query(selector, animation, options = null) {
876
- return { type: AnimationMetadataType.Query, selector, animation, options };
103
+ return {
104
+ type: AnimationMetadataType.Query,
105
+ selector,
106
+ animation,
107
+ options
108
+ };
877
109
  }
878
- /**
879
- * Use within an animation `query()` call to issue a timing gap after
880
- * each queried item is animated.
881
- *
882
- * @param timings A delay value.
883
- * @param animation One ore more animation steps.
884
- * @returns An object that encapsulates the stagger data.
885
- *
886
- * @usageNotes
887
- * In the following example, a container element wraps a list of items stamped out
888
- * by an `@for` block. The container element contains an animation trigger that will later be set
889
- * to query for each of the inner items.
890
- *
891
- * Each time items are added, the opacity fade-in animation runs,
892
- * and each removed item is faded out.
893
- * When either of these animations occur, the stagger effect is
894
- * applied after each item's animation is started.
895
- *
896
- * ```html
897
- * <!-- list.component.html -->
898
- * <button (click)="toggle()">Show / Hide Items</button>
899
- * <hr />
900
- * <div [@listAnimation]="items.length">
901
- * @for(item of items; track $index) {
902
- * <div>{{ item }}</div>
903
- * }
904
- * </div>
905
- * ```
906
- *
907
- * Here is the component code:
908
- *
909
- * ```ts
910
- * import {trigger, transition, style, animate, query, stagger} from '@angular/animations';
911
- * @Component({
912
- * templateUrl: 'list.component.html',
913
- * animations: [
914
- * trigger('listAnimation', [
915
- * ...
916
- * ])
917
- * ]
918
- * })
919
- * class ListComponent {
920
- * items = [];
921
- *
922
- * showItems() {
923
- * this.items = [0,1,2,3,4];
924
- * }
925
- *
926
- * hideItems() {
927
- * this.items = [];
928
- * }
929
- *
930
- * toggle() {
931
- * this.items.length ? this.hideItems() : this.showItems();
932
- * }
933
- * }
934
- * ```
935
- *
936
- * Here is the animation trigger code:
937
- *
938
- * ```ts
939
- * trigger('listAnimation', [
940
- * transition('* => *', [ // each time the binding value changes
941
- * query(':leave', [
942
- * stagger(100, [
943
- * animate('0.5s', style({ opacity: 0 }))
944
- * ])
945
- * ]),
946
- * query(':enter', [
947
- * style({ opacity: 0 }),
948
- * stagger(100, [
949
- * animate('0.5s', style({ opacity: 1 }))
950
- * ])
951
- * ])
952
- * ])
953
- * ])
954
- * ```
955
- *
956
- * @publicApi
957
- *
958
- * @deprecated 20.2 Use `animate.enter` or `animate.leave` instead. Intent to remove in v23
959
- */
960
110
  function stagger(timings, animation) {
961
- return { type: AnimationMetadataType.Stagger, timings, animation };
111
+ return {
112
+ type: AnimationMetadataType.Stagger,
113
+ timings,
114
+ animation
115
+ };
962
116
  }
963
117
 
964
- /**
965
- * An empty programmatic controller for reusable animations.
966
- * Used internally when animations are disabled, to avoid
967
- * checking for the null case when an animation player is expected.
968
- *
969
- * @see {@link animate}
970
- * @see {@link AnimationPlayer}
971
- *
972
- * @publicApi
973
- *
974
- * @deprecated 20.2 Use `animate.enter` or `animate.leave` instead. Intent to remove in v23
975
- */
976
118
  class NoopAnimationPlayer {
977
- _onDoneFns = [];
978
- _onStartFns = [];
979
- _onDestroyFns = [];
980
- _originalOnDoneFns = [];
981
- _originalOnStartFns = [];
982
- _started = false;
983
- _destroyed = false;
984
- _finished = false;
985
- _position = 0;
986
- parentPlayer = null;
987
- totalTime;
988
- constructor(duration = 0, delay = 0) {
989
- this.totalTime = duration + delay;
990
- }
991
- _onFinish() {
992
- if (!this._finished) {
993
- this._finished = true;
994
- this._onDoneFns.forEach((fn) => fn());
995
- this._onDoneFns = [];
996
- }
997
- }
998
- onStart(fn) {
999
- this._originalOnStartFns.push(fn);
1000
- this._onStartFns.push(fn);
1001
- }
1002
- onDone(fn) {
1003
- this._originalOnDoneFns.push(fn);
1004
- this._onDoneFns.push(fn);
1005
- }
1006
- onDestroy(fn) {
1007
- this._onDestroyFns.push(fn);
1008
- }
1009
- hasStarted() {
1010
- return this._started;
1011
- }
1012
- init() { }
1013
- play() {
1014
- if (!this.hasStarted()) {
1015
- this._onStart();
1016
- this.triggerMicrotask();
1017
- }
1018
- this._started = true;
1019
- }
1020
- /** @internal */
1021
- triggerMicrotask() {
1022
- queueMicrotask(() => this._onFinish());
1023
- }
1024
- _onStart() {
1025
- this._onStartFns.forEach((fn) => fn());
1026
- this._onStartFns = [];
1027
- }
1028
- pause() { }
1029
- restart() { }
1030
- finish() {
1031
- this._onFinish();
1032
- }
1033
- destroy() {
1034
- if (!this._destroyed) {
1035
- this._destroyed = true;
1036
- if (!this.hasStarted()) {
1037
- this._onStart();
1038
- }
1039
- this.finish();
1040
- this._onDestroyFns.forEach((fn) => fn());
1041
- this._onDestroyFns = [];
1042
- }
1043
- }
1044
- reset() {
1045
- this._started = false;
1046
- this._finished = false;
1047
- this._onStartFns = this._originalOnStartFns;
1048
- this._onDoneFns = this._originalOnDoneFns;
1049
- }
1050
- setPosition(position) {
1051
- this._position = this.totalTime ? position * this.totalTime : 1;
1052
- }
1053
- getPosition() {
1054
- return this.totalTime ? this._position / this.totalTime : 1;
1055
- }
1056
- /** @internal */
1057
- triggerCallback(phaseName) {
1058
- const methods = phaseName == 'start' ? this._onStartFns : this._onDoneFns;
1059
- methods.forEach((fn) => fn());
1060
- methods.length = 0;
1061
- }
119
+ _onDoneFns = [];
120
+ _onStartFns = [];
121
+ _onDestroyFns = [];
122
+ _originalOnDoneFns = [];
123
+ _originalOnStartFns = [];
124
+ _started = false;
125
+ _destroyed = false;
126
+ _finished = false;
127
+ _position = 0;
128
+ parentPlayer = null;
129
+ totalTime;
130
+ constructor(duration = 0, delay = 0) {
131
+ this.totalTime = duration + delay;
132
+ }
133
+ _onFinish() {
134
+ if (!this._finished) {
135
+ this._finished = true;
136
+ this._onDoneFns.forEach(fn => fn());
137
+ this._onDoneFns = [];
138
+ }
139
+ }
140
+ onStart(fn) {
141
+ this._originalOnStartFns.push(fn);
142
+ this._onStartFns.push(fn);
143
+ }
144
+ onDone(fn) {
145
+ this._originalOnDoneFns.push(fn);
146
+ this._onDoneFns.push(fn);
147
+ }
148
+ onDestroy(fn) {
149
+ this._onDestroyFns.push(fn);
150
+ }
151
+ hasStarted() {
152
+ return this._started;
153
+ }
154
+ init() {}
155
+ play() {
156
+ if (!this.hasStarted()) {
157
+ this._onStart();
158
+ this.triggerMicrotask();
159
+ }
160
+ this._started = true;
161
+ }
162
+ triggerMicrotask() {
163
+ queueMicrotask(() => this._onFinish());
164
+ }
165
+ _onStart() {
166
+ this._onStartFns.forEach(fn => fn());
167
+ this._onStartFns = [];
168
+ }
169
+ pause() {}
170
+ restart() {}
171
+ finish() {
172
+ this._onFinish();
173
+ }
174
+ destroy() {
175
+ if (!this._destroyed) {
176
+ this._destroyed = true;
177
+ if (!this.hasStarted()) {
178
+ this._onStart();
179
+ }
180
+ this.finish();
181
+ this._onDestroyFns.forEach(fn => fn());
182
+ this._onDestroyFns = [];
183
+ }
184
+ }
185
+ reset() {
186
+ this._started = false;
187
+ this._finished = false;
188
+ this._onStartFns = this._originalOnStartFns;
189
+ this._onDoneFns = this._originalOnDoneFns;
190
+ }
191
+ setPosition(position) {
192
+ this._position = this.totalTime ? position * this.totalTime : 1;
193
+ }
194
+ getPosition() {
195
+ return this.totalTime ? this._position / this.totalTime : 1;
196
+ }
197
+ triggerCallback(phaseName) {
198
+ const methods = phaseName == 'start' ? this._onStartFns : this._onDoneFns;
199
+ methods.forEach(fn => fn());
200
+ methods.length = 0;
201
+ }
1062
202
  }
1063
203
 
1064
- /**
1065
- * A programmatic controller for a group of reusable animations.
1066
- * Used internally to control animations.
1067
- *
1068
- * @see {@link AnimationPlayer}
1069
- * @see {@link animations/group group}
1070
- *
1071
- */
1072
204
  class AnimationGroupPlayer {
1073
- _onDoneFns = [];
1074
- _onStartFns = [];
1075
- _finished = false;
1076
- _started = false;
1077
- _destroyed = false;
1078
- _onDestroyFns = [];
1079
- parentPlayer = null;
1080
- totalTime = 0;
1081
- players;
1082
- constructor(_players) {
1083
- this.players = _players;
1084
- let doneCount = 0;
1085
- let destroyCount = 0;
1086
- let startCount = 0;
1087
- const total = this.players.length;
1088
- if (total == 0) {
1089
- queueMicrotask(() => this._onFinish());
1090
- }
1091
- else {
1092
- this.players.forEach((player) => {
1093
- player.onDone(() => {
1094
- if (++doneCount == total) {
1095
- this._onFinish();
1096
- }
1097
- });
1098
- player.onDestroy(() => {
1099
- if (++destroyCount == total) {
1100
- this._onDestroy();
1101
- }
1102
- });
1103
- player.onStart(() => {
1104
- if (++startCount == total) {
1105
- this._onStart();
1106
- }
1107
- });
1108
- });
1109
- }
1110
- this.totalTime = this.players.reduce((time, player) => Math.max(time, player.totalTime), 0);
1111
- }
1112
- _onFinish() {
1113
- if (!this._finished) {
1114
- this._finished = true;
1115
- this._onDoneFns.forEach((fn) => fn());
1116
- this._onDoneFns = [];
1117
- }
1118
- }
1119
- init() {
1120
- this.players.forEach((player) => player.init());
1121
- }
1122
- onStart(fn) {
1123
- this._onStartFns.push(fn);
1124
- }
1125
- _onStart() {
1126
- if (!this.hasStarted()) {
1127
- this._started = true;
1128
- this._onStartFns.forEach((fn) => fn());
1129
- this._onStartFns = [];
1130
- }
1131
- }
1132
- onDone(fn) {
1133
- this._onDoneFns.push(fn);
1134
- }
1135
- onDestroy(fn) {
1136
- this._onDestroyFns.push(fn);
1137
- }
1138
- hasStarted() {
1139
- return this._started;
1140
- }
1141
- play() {
1142
- if (!this.parentPlayer) {
1143
- this.init();
1144
- }
1145
- this._onStart();
1146
- this.players.forEach((player) => player.play());
1147
- }
1148
- pause() {
1149
- this.players.forEach((player) => player.pause());
1150
- }
1151
- restart() {
1152
- this.players.forEach((player) => player.restart());
1153
- }
1154
- finish() {
1155
- this._onFinish();
1156
- this.players.forEach((player) => player.finish());
1157
- }
1158
- destroy() {
1159
- this._onDestroy();
1160
- }
1161
- _onDestroy() {
1162
- if (!this._destroyed) {
1163
- this._destroyed = true;
205
+ _onDoneFns = [];
206
+ _onStartFns = [];
207
+ _finished = false;
208
+ _started = false;
209
+ _destroyed = false;
210
+ _onDestroyFns = [];
211
+ parentPlayer = null;
212
+ totalTime = 0;
213
+ players;
214
+ constructor(_players) {
215
+ this.players = _players;
216
+ let doneCount = 0;
217
+ let destroyCount = 0;
218
+ let startCount = 0;
219
+ const total = this.players.length;
220
+ if (total == 0) {
221
+ queueMicrotask(() => this._onFinish());
222
+ } else {
223
+ this.players.forEach(player => {
224
+ player.onDone(() => {
225
+ if (++doneCount == total) {
1164
226
  this._onFinish();
1165
- this.players.forEach((player) => player.destroy());
1166
- this._onDestroyFns.forEach((fn) => fn());
1167
- this._onDestroyFns = [];
1168
- }
1169
- }
1170
- reset() {
1171
- this.players.forEach((player) => player.reset());
1172
- this._destroyed = false;
1173
- this._finished = false;
1174
- this._started = false;
1175
- }
1176
- setPosition(p) {
1177
- const timeAtPosition = p * this.totalTime;
1178
- this.players.forEach((player) => {
1179
- const position = player.totalTime ? Math.min(1, timeAtPosition / player.totalTime) : 1;
1180
- player.setPosition(position);
227
+ }
1181
228
  });
1182
- }
1183
- getPosition() {
1184
- const longestPlayer = this.players.reduce((longestSoFar, player) => {
1185
- const newPlayerIsLongest = longestSoFar === null || player.totalTime > longestSoFar.totalTime;
1186
- return newPlayerIsLongest ? player : longestSoFar;
1187
- }, null);
1188
- return longestPlayer != null ? longestPlayer.getPosition() : 0;
1189
- }
1190
- beforeDestroy() {
1191
- this.players.forEach((player) => {
1192
- if (player.beforeDestroy) {
1193
- player.beforeDestroy();
1194
- }
229
+ player.onDestroy(() => {
230
+ if (++destroyCount == total) {
231
+ this._onDestroy();
232
+ }
1195
233
  });
1196
- }
1197
- /** @internal */
1198
- triggerCallback(phaseName) {
1199
- const methods = phaseName == 'start' ? this._onStartFns : this._onDoneFns;
1200
- methods.forEach((fn) => fn());
1201
- methods.length = 0;
1202
- }
234
+ player.onStart(() => {
235
+ if (++startCount == total) {
236
+ this._onStart();
237
+ }
238
+ });
239
+ });
240
+ }
241
+ this.totalTime = this.players.reduce((time, player) => Math.max(time, player.totalTime), 0);
242
+ }
243
+ _onFinish() {
244
+ if (!this._finished) {
245
+ this._finished = true;
246
+ this._onDoneFns.forEach(fn => fn());
247
+ this._onDoneFns = [];
248
+ }
249
+ }
250
+ init() {
251
+ this.players.forEach(player => player.init());
252
+ }
253
+ onStart(fn) {
254
+ this._onStartFns.push(fn);
255
+ }
256
+ _onStart() {
257
+ if (!this.hasStarted()) {
258
+ this._started = true;
259
+ this._onStartFns.forEach(fn => fn());
260
+ this._onStartFns = [];
261
+ }
262
+ }
263
+ onDone(fn) {
264
+ this._onDoneFns.push(fn);
265
+ }
266
+ onDestroy(fn) {
267
+ this._onDestroyFns.push(fn);
268
+ }
269
+ hasStarted() {
270
+ return this._started;
271
+ }
272
+ play() {
273
+ if (!this.parentPlayer) {
274
+ this.init();
275
+ }
276
+ this._onStart();
277
+ this.players.forEach(player => player.play());
278
+ }
279
+ pause() {
280
+ this.players.forEach(player => player.pause());
281
+ }
282
+ restart() {
283
+ this.players.forEach(player => player.restart());
284
+ }
285
+ finish() {
286
+ this._onFinish();
287
+ this.players.forEach(player => player.finish());
288
+ }
289
+ destroy() {
290
+ this._onDestroy();
291
+ }
292
+ _onDestroy() {
293
+ if (!this._destroyed) {
294
+ this._destroyed = true;
295
+ this._onFinish();
296
+ this.players.forEach(player => player.destroy());
297
+ this._onDestroyFns.forEach(fn => fn());
298
+ this._onDestroyFns = [];
299
+ }
300
+ }
301
+ reset() {
302
+ this.players.forEach(player => player.reset());
303
+ this._destroyed = false;
304
+ this._finished = false;
305
+ this._started = false;
306
+ }
307
+ setPosition(p) {
308
+ const timeAtPosition = p * this.totalTime;
309
+ this.players.forEach(player => {
310
+ const position = player.totalTime ? Math.min(1, timeAtPosition / player.totalTime) : 1;
311
+ player.setPosition(position);
312
+ });
313
+ }
314
+ getPosition() {
315
+ const longestPlayer = this.players.reduce((longestSoFar, player) => {
316
+ const newPlayerIsLongest = longestSoFar === null || player.totalTime > longestSoFar.totalTime;
317
+ return newPlayerIsLongest ? player : longestSoFar;
318
+ }, null);
319
+ return longestPlayer != null ? longestPlayer.getPosition() : 0;
320
+ }
321
+ beforeDestroy() {
322
+ this.players.forEach(player => {
323
+ if (player.beforeDestroy) {
324
+ player.beforeDestroy();
325
+ }
326
+ });
327
+ }
328
+ triggerCallback(phaseName) {
329
+ const methods = phaseName == 'start' ? this._onStartFns : this._onDoneFns;
330
+ methods.forEach(fn => fn());
331
+ methods.length = 0;
332
+ }
1203
333
  }
1204
334
 
1205
335
  const ɵPRE_STYLE = '!';