animations.mjs 46 KB

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