animejs 4.1.3 → 4.2.0-beta.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.
Files changed (191) hide show
  1. package/README.md +12 -8
  2. package/{lib → dist/bundles}/anime.esm.js +5237 -5049
  3. package/dist/bundles/anime.esm.min.js +7 -0
  4. package/dist/bundles/anime.umd.js +8621 -0
  5. package/dist/bundles/anime.umd.min.js +7 -0
  6. package/dist/modules/animatable/animatable.cjs +150 -0
  7. package/dist/modules/animatable/animatable.d.ts +28 -0
  8. package/dist/modules/animatable/animatable.js +147 -0
  9. package/dist/modules/animatable/index.cjs +15 -0
  10. package/dist/modules/animatable/index.d.ts +1 -0
  11. package/dist/modules/animatable/index.js +8 -0
  12. package/dist/modules/animation/additive.cjs +82 -0
  13. package/dist/modules/animation/additive.d.ts +15 -0
  14. package/dist/modules/animation/additive.js +79 -0
  15. package/dist/modules/animation/animation.cjs +660 -0
  16. package/dist/modules/animation/animation.d.ts +47 -0
  17. package/dist/modules/animation/animation.js +657 -0
  18. package/dist/modules/animation/composition.cjs +383 -0
  19. package/dist/modules/animation/composition.d.ts +10 -0
  20. package/dist/modules/animation/composition.js +377 -0
  21. package/dist/modules/animation/index.cjs +15 -0
  22. package/dist/modules/animation/index.d.ts +1 -0
  23. package/dist/modules/animation/index.js +8 -0
  24. package/dist/modules/core/clock.cjs +110 -0
  25. package/dist/modules/core/clock.d.ts +51 -0
  26. package/dist/modules/core/clock.js +108 -0
  27. package/dist/modules/core/colors.cjs +102 -0
  28. package/dist/modules/core/colors.d.ts +2 -0
  29. package/dist/modules/core/colors.js +100 -0
  30. package/dist/modules/core/consts.cjs +154 -0
  31. package/dist/modules/core/consts.d.ts +59 -0
  32. package/dist/modules/core/consts.js +121 -0
  33. package/dist/modules/core/globals.cjs +77 -0
  34. package/dist/modules/core/globals.d.ts +29 -0
  35. package/dist/modules/core/globals.js +72 -0
  36. package/dist/modules/core/helpers.cjs +304 -0
  37. package/dist/modules/core/helpers.d.ts +43 -0
  38. package/dist/modules/core/helpers.js +261 -0
  39. package/dist/modules/core/render.cjs +389 -0
  40. package/dist/modules/core/render.d.ts +4 -0
  41. package/dist/modules/core/render.js +386 -0
  42. package/dist/modules/core/styles.cjs +116 -0
  43. package/dist/modules/core/styles.d.ts +5 -0
  44. package/dist/modules/core/styles.js +113 -0
  45. package/dist/modules/core/targets.cjs +136 -0
  46. package/dist/modules/core/targets.d.ts +118 -0
  47. package/dist/modules/core/targets.js +132 -0
  48. package/dist/modules/core/transforms.cjs +49 -0
  49. package/dist/modules/core/transforms.d.ts +2 -0
  50. package/dist/modules/core/transforms.js +47 -0
  51. package/dist/modules/core/units.cjs +67 -0
  52. package/dist/modules/core/units.d.ts +3 -0
  53. package/dist/modules/core/units.js +65 -0
  54. package/dist/modules/core/values.cjs +215 -0
  55. package/dist/modules/core/values.d.ts +14 -0
  56. package/dist/modules/core/values.js +205 -0
  57. package/dist/modules/draggable/draggable.cjs +1226 -0
  58. package/dist/modules/draggable/draggable.d.ts +272 -0
  59. package/dist/modules/draggable/draggable.js +1223 -0
  60. package/dist/modules/draggable/index.cjs +15 -0
  61. package/dist/modules/draggable/index.d.ts +1 -0
  62. package/dist/modules/draggable/index.js +8 -0
  63. package/dist/modules/easings/cubic-bezier.cjs +64 -0
  64. package/dist/modules/easings/cubic-bezier.d.ts +2 -0
  65. package/dist/modules/easings/cubic-bezier.js +62 -0
  66. package/dist/modules/easings/eases.cjs +149 -0
  67. package/dist/modules/easings/eases.d.ts +111 -0
  68. package/dist/modules/easings/eases.js +146 -0
  69. package/dist/modules/easings/index.cjs +24 -0
  70. package/dist/modules/easings/index.d.ts +6 -0
  71. package/dist/modules/easings/index.js +13 -0
  72. package/dist/modules/easings/irregular.cjs +41 -0
  73. package/dist/modules/easings/irregular.d.ts +2 -0
  74. package/dist/modules/easings/irregular.js +39 -0
  75. package/dist/modules/easings/linear.cjs +59 -0
  76. package/dist/modules/easings/linear.d.ts +2 -0
  77. package/dist/modules/easings/linear.js +57 -0
  78. package/dist/modules/easings/none.cjs +19 -0
  79. package/dist/modules/easings/none.d.ts +8 -0
  80. package/dist/modules/easings/none.js +17 -0
  81. package/dist/modules/easings/parser.cjs +59 -0
  82. package/dist/modules/easings/parser.d.ts +21 -0
  83. package/dist/modules/easings/parser.js +55 -0
  84. package/dist/modules/easings/steps.cjs +30 -0
  85. package/dist/modules/easings/steps.d.ts +2 -0
  86. package/dist/modules/easings/steps.js +28 -0
  87. package/dist/modules/engine/engine.cjs +168 -0
  88. package/dist/modules/engine/engine.d.ts +21 -0
  89. package/dist/modules/engine/engine.js +166 -0
  90. package/dist/modules/engine/index.cjs +14 -0
  91. package/dist/modules/engine/index.d.ts +1 -0
  92. package/dist/modules/engine/index.js +8 -0
  93. package/dist/modules/events/index.cjs +16 -0
  94. package/dist/modules/events/index.d.ts +1 -0
  95. package/dist/modules/events/index.js +8 -0
  96. package/dist/modules/events/scroll.cjs +936 -0
  97. package/dist/modules/events/scroll.d.ts +189 -0
  98. package/dist/modules/events/scroll.js +932 -0
  99. package/dist/modules/index.cjs +103 -0
  100. package/dist/modules/index.d.ts +19 -0
  101. package/dist/modules/index.js +42 -0
  102. package/dist/modules/scope/index.cjs +15 -0
  103. package/dist/modules/scope/index.d.ts +1 -0
  104. package/dist/modules/scope/index.js +8 -0
  105. package/dist/modules/scope/scope.cjs +254 -0
  106. package/dist/modules/scope/scope.d.ts +115 -0
  107. package/dist/modules/scope/scope.js +251 -0
  108. package/dist/modules/spring/index.cjs +15 -0
  109. package/dist/modules/spring/index.d.ts +1 -0
  110. package/dist/modules/spring/index.js +8 -0
  111. package/dist/modules/spring/spring.cjs +133 -0
  112. package/dist/modules/spring/spring.d.ts +37 -0
  113. package/dist/modules/spring/spring.js +130 -0
  114. package/dist/modules/svg/drawable.cjs +119 -0
  115. package/dist/modules/svg/drawable.d.ts +3 -0
  116. package/dist/modules/svg/drawable.js +117 -0
  117. package/dist/modules/svg/helpers.cjs +30 -0
  118. package/dist/modules/svg/helpers.d.ts +2 -0
  119. package/dist/modules/svg/helpers.js +28 -0
  120. package/dist/modules/svg/index.cjs +18 -0
  121. package/dist/modules/svg/index.d.ts +3 -0
  122. package/dist/modules/svg/index.js +10 -0
  123. package/dist/modules/svg/morphto.cjs +58 -0
  124. package/dist/modules/svg/morphto.d.ts +3 -0
  125. package/dist/modules/svg/morphto.js +56 -0
  126. package/dist/modules/svg/motionpath.cjs +79 -0
  127. package/dist/modules/svg/motionpath.d.ts +7 -0
  128. package/dist/modules/svg/motionpath.js +77 -0
  129. package/dist/modules/text/index.cjs +16 -0
  130. package/dist/modules/text/index.d.ts +1 -0
  131. package/dist/modules/text/index.js +8 -0
  132. package/dist/modules/text/split.cjs +488 -0
  133. package/dist/modules/text/split.d.ts +62 -0
  134. package/dist/modules/text/split.js +484 -0
  135. package/dist/modules/timeline/index.cjs +15 -0
  136. package/dist/modules/timeline/index.d.ts +1 -0
  137. package/dist/modules/timeline/index.js +8 -0
  138. package/dist/modules/timeline/position.cjs +72 -0
  139. package/dist/modules/timeline/position.d.ts +3 -0
  140. package/dist/modules/timeline/position.js +70 -0
  141. package/dist/modules/timeline/timeline.cjs +312 -0
  142. package/dist/modules/timeline/timeline.d.ts +163 -0
  143. package/dist/modules/timeline/timeline.js +309 -0
  144. package/dist/modules/timer/index.cjs +15 -0
  145. package/dist/modules/timer/index.d.ts +1 -0
  146. package/dist/modules/timer/index.js +8 -0
  147. package/dist/modules/timer/timer.cjs +491 -0
  148. package/dist/modules/timer/timer.d.ts +141 -0
  149. package/dist/modules/timer/timer.js +488 -0
  150. package/dist/modules/types/index.d.ts +387 -0
  151. package/dist/modules/utils/chainable.cjs +190 -0
  152. package/dist/modules/utils/chainable.d.ts +135 -0
  153. package/dist/modules/utils/chainable.js +177 -0
  154. package/dist/modules/utils/index.cjs +43 -0
  155. package/dist/modules/utils/index.d.ts +5 -0
  156. package/dist/modules/utils/index.js +14 -0
  157. package/dist/modules/utils/number.cjs +97 -0
  158. package/dist/modules/utils/number.d.ts +9 -0
  159. package/dist/modules/utils/number.js +85 -0
  160. package/dist/modules/utils/random.cjs +77 -0
  161. package/dist/modules/utils/random.d.ts +22 -0
  162. package/dist/modules/utils/random.js +72 -0
  163. package/dist/modules/utils/stagger.cjs +122 -0
  164. package/dist/modules/utils/stagger.d.ts +30 -0
  165. package/dist/modules/utils/stagger.js +120 -0
  166. package/dist/modules/utils/target.cjs +130 -0
  167. package/dist/modules/utils/target.d.ts +126 -0
  168. package/dist/modules/utils/target.js +125 -0
  169. package/dist/modules/utils/time.cjs +57 -0
  170. package/dist/modules/utils/time.d.ts +5 -0
  171. package/dist/modules/utils/time.js +54 -0
  172. package/dist/modules/waapi/composition.cjs +89 -0
  173. package/dist/modules/waapi/composition.d.ts +4 -0
  174. package/dist/modules/waapi/composition.js +86 -0
  175. package/dist/modules/waapi/index.cjs +15 -0
  176. package/dist/modules/waapi/index.d.ts +1 -0
  177. package/dist/modules/waapi/index.js +8 -0
  178. package/dist/modules/waapi/waapi.cjs +473 -0
  179. package/dist/modules/waapi/waapi.d.ts +114 -0
  180. package/dist/modules/waapi/waapi.js +470 -0
  181. package/package.json +130 -33
  182. package/lib/anime.cjs +0 -9
  183. package/lib/anime.esm.min.js +0 -9
  184. package/lib/anime.iife.js +0 -9
  185. package/lib/anime.iife.min.js +0 -9
  186. package/lib/anime.min.cjs +0 -9
  187. package/lib/anime.umd.js +0 -9
  188. package/lib/anime.umd.min.js +0 -9
  189. package/lib/gui/index.js +0 -6341
  190. package/types/index.d.ts +0 -1126
  191. package/types/index.js +0 -7388
@@ -0,0 +1,932 @@
1
+ /**
2
+ * Anime.js - events - ESM
3
+ * @version v4.2.0
4
+ * @license MIT
5
+ * @copyright 2025 - Julian Garnier
6
+ */
7
+
8
+ import { noop, doc, isDomSymbol, relativeValuesExecRgx, win } from '../core/consts.js';
9
+ import { scope, globals } from '../core/globals.js';
10
+ import { isUnd, isNum, addChild, forEachChildren, round, isStr, isObj, removeChild, clamp, lerp, isFnc } from '../core/helpers.js';
11
+ import { parseTargets } from '../core/targets.js';
12
+ import { setValue, getRelativeValue, decomposeRawValue, decomposedOriginalValue } from '../core/values.js';
13
+ import { convertValueUnit } from '../core/units.js';
14
+ import { Timer } from '../timer/timer.js';
15
+ import { get, set } from '../utils/target.js';
16
+ import { sync } from '../utils/time.js';
17
+ import { none } from '../easings/none.js';
18
+ import { parseEase } from '../easings/eases.js';
19
+
20
+ /**
21
+ * @import {
22
+ * TargetsParam,
23
+ * EasingFunction,
24
+ * Callback,
25
+ * EasingParam,
26
+ * ScrollThresholdValue,
27
+ * ScrollObserverParams,
28
+ * Tickable,
29
+ * ScrollThresholdParam,
30
+ * ScrollThresholdCallback,
31
+ * } from '../types/index.js'
32
+ */
33
+
34
+ /**
35
+ * @import {
36
+ * JSAnimation,
37
+ * } from '../animation/animation.js'
38
+ */
39
+
40
+ /**
41
+ * @import {
42
+ * WAAPIAnimation,
43
+ * } from '../waapi/waapi.js'
44
+ */
45
+
46
+ /**
47
+ * @import {
48
+ * Timeline,
49
+ * } from '../timeline/timeline.js'
50
+ */
51
+
52
+ /**
53
+ * @return {Number}
54
+ */
55
+ const getMaxViewHeight = () => {
56
+ const $el = doc.createElement('div');
57
+ doc.body.appendChild($el);
58
+ $el.style.height = '100lvh';
59
+ const height = $el.offsetHeight;
60
+ doc.body.removeChild($el);
61
+ return height;
62
+ };
63
+
64
+ /**
65
+ * @template {ScrollThresholdValue|String|Number|Boolean|Function|Object} T
66
+ * @param {T | ((observer: ScrollObserver) => T)} value
67
+ * @param {ScrollObserver} scroller
68
+ * @return {T}
69
+ */
70
+ const parseScrollObserverFunctionParameter = (value, scroller) => value && isFnc(value) ? /** @type {Function} */(value)(scroller) : /** @type {T} */(value);
71
+
72
+ const scrollContainers = new Map();
73
+
74
+ class ScrollContainer {
75
+ /**
76
+ * @param {HTMLElement} $el
77
+ */
78
+ constructor($el) {
79
+ /** @type {HTMLElement} */
80
+ this.element = $el;
81
+ /** @type {Boolean} */
82
+ this.useWin = this.element === doc.body;
83
+ /** @type {Number} */
84
+ this.winWidth = 0;
85
+ /** @type {Number} */
86
+ this.winHeight = 0;
87
+ /** @type {Number} */
88
+ this.width = 0;
89
+ /** @type {Number} */
90
+ this.height = 0;
91
+ /** @type {Number} */
92
+ this.left = 0;
93
+ /** @type {Number} */
94
+ this.top = 0;
95
+ /** @type {Number} */
96
+ this.zIndex = 0;
97
+ /** @type {Number} */
98
+ this.scrollX = 0;
99
+ /** @type {Number} */
100
+ this.scrollY = 0;
101
+ /** @type {Number} */
102
+ this.prevScrollX = 0;
103
+ /** @type {Number} */
104
+ this.prevScrollY = 0;
105
+ /** @type {Number} */
106
+ this.scrollWidth = 0;
107
+ /** @type {Number} */
108
+ this.scrollHeight = 0;
109
+ /** @type {Number} */
110
+ this.velocity = 0;
111
+ /** @type {Boolean} */
112
+ this.backwardX = false;
113
+ /** @type {Boolean} */
114
+ this.backwardY = false;
115
+ /** @type {Timer} */
116
+ this.scrollTicker = new Timer({
117
+ autoplay: false,
118
+ onBegin: () => this.dataTimer.resume(),
119
+ onUpdate: () => {
120
+ const backwards = this.backwardX || this.backwardY;
121
+ forEachChildren(this, (/** @type {ScrollObserver} */child) => child.handleScroll(), backwards);
122
+ },
123
+ onComplete: () => this.dataTimer.pause()
124
+ }).init();
125
+ /** @type {Timer} */
126
+ this.dataTimer = new Timer({
127
+ autoplay: false,
128
+ frameRate: 30,
129
+ onUpdate: (/** @type {Timer} */self) => {
130
+ const dt = self.deltaTime;
131
+ const px = this.prevScrollX;
132
+ const py = this.prevScrollY;
133
+ const nx = this.scrollX;
134
+ const ny = this.scrollY;
135
+ const dx = px - nx;
136
+ const dy = py - ny;
137
+ this.prevScrollX = nx;
138
+ this.prevScrollY = ny;
139
+ if (dx) this.backwardX = px > nx;
140
+ if (dy) this.backwardY = py > ny;
141
+ this.velocity = round(dt > 0 ? Math.sqrt(dx * dx + dy * dy) / dt : 0, 5);
142
+ }
143
+ }).init();
144
+ /** @type {Timer} */
145
+ this.resizeTicker = new Timer({
146
+ autoplay: false,
147
+ duration: 250 * globals.timeScale,
148
+ onComplete: () => {
149
+ this.updateWindowBounds();
150
+ this.refreshScrollObservers();
151
+ this.handleScroll();
152
+ }
153
+ }).init();
154
+ /** @type {Timer} */
155
+ this.wakeTicker = new Timer({
156
+ autoplay: false,
157
+ duration: 500 * globals.timeScale,
158
+ onBegin: () => {
159
+ this.scrollTicker.resume();
160
+ },
161
+ onComplete: () => {
162
+ this.scrollTicker.pause();
163
+ }
164
+ }).init();
165
+ /** @type {ScrollObserver} */
166
+ this._head = null;
167
+ /** @type {ScrollObserver} */
168
+ this._tail = null;
169
+ this.updateScrollCoords();
170
+ this.updateWindowBounds();
171
+ this.updateBounds();
172
+ this.refreshScrollObservers();
173
+ this.handleScroll();
174
+ this.resizeObserver = new ResizeObserver(() => this.resizeTicker.restart());
175
+ this.resizeObserver.observe(this.element);
176
+ (this.useWin ? win : this.element).addEventListener('scroll', this, false);
177
+ }
178
+
179
+ updateScrollCoords() {
180
+ const useWin = this.useWin;
181
+ const $el = this.element;
182
+ this.scrollX = round(useWin ? win.scrollX : $el.scrollLeft, 0);
183
+ this.scrollY = round(useWin ? win.scrollY : $el.scrollTop, 0);
184
+ }
185
+
186
+ updateWindowBounds() {
187
+ this.winWidth = win.innerWidth;
188
+ this.winHeight = getMaxViewHeight();
189
+ }
190
+
191
+ updateBounds() {
192
+ const style = getComputedStyle(this.element);
193
+ const $el = this.element;
194
+ this.scrollWidth = $el.scrollWidth + parseFloat(style.marginLeft) + parseFloat(style.marginRight);
195
+ this.scrollHeight = $el.scrollHeight + parseFloat(style.marginTop) + parseFloat(style.marginBottom);
196
+ this.updateWindowBounds();
197
+ let width, height;
198
+ if (this.useWin) {
199
+ width = this.winWidth;
200
+ height = this.winHeight;
201
+ } else {
202
+ const elRect = $el.getBoundingClientRect();
203
+ width = $el.clientWidth;
204
+ height = $el.clientHeight;
205
+ this.top = elRect.top;
206
+ this.left = elRect.left;
207
+ }
208
+ this.width = width;
209
+ this.height = height;
210
+ }
211
+
212
+ refreshScrollObservers() {
213
+ forEachChildren(this, (/** @type {ScrollObserver} */child) => {
214
+ if (child._debug) {
215
+ child.removeDebug();
216
+ }
217
+ });
218
+ this.updateBounds();
219
+ forEachChildren(this, (/** @type {ScrollObserver} */child) => {
220
+ child.refresh();
221
+ if (child._debug) {
222
+ child.debug();
223
+ }
224
+ });
225
+ }
226
+
227
+ refresh() {
228
+ this.updateWindowBounds();
229
+ this.updateBounds();
230
+ this.refreshScrollObservers();
231
+ this.handleScroll();
232
+ }
233
+
234
+ handleScroll() {
235
+ this.updateScrollCoords();
236
+ this.wakeTicker.restart();
237
+ }
238
+
239
+ /**
240
+ * @param {Event} e
241
+ */
242
+ handleEvent(e) {
243
+ switch (e.type) {
244
+ case 'scroll':
245
+ this.handleScroll();
246
+ break;
247
+ }
248
+ }
249
+
250
+ revert() {
251
+ this.scrollTicker.cancel();
252
+ this.dataTimer.cancel();
253
+ this.resizeTicker.cancel();
254
+ this.wakeTicker.cancel();
255
+ this.resizeObserver.disconnect();
256
+ (this.useWin ? win : this.element).removeEventListener('scroll', this);
257
+ scrollContainers.delete(this.element);
258
+ }
259
+ }
260
+
261
+ /**
262
+ * @param {TargetsParam} target
263
+ * @return {ScrollContainer}
264
+ */
265
+ const registerAndGetScrollContainer = target => {
266
+ const $el = /** @type {HTMLElement} */(target ? parseTargets(target)[0] || doc.body : doc.body);
267
+ let scrollContainer = scrollContainers.get($el);
268
+ if (!scrollContainer) {
269
+ scrollContainer = new ScrollContainer($el);
270
+ scrollContainers.set($el, scrollContainer);
271
+ }
272
+ return scrollContainer;
273
+ };
274
+
275
+ /**
276
+ * @param {HTMLElement} $el
277
+ * @param {Number|string} v
278
+ * @param {Number} size
279
+ * @param {Number} [under]
280
+ * @param {Number} [over]
281
+ * @return {Number}
282
+ */
283
+ const convertValueToPx = ($el, v, size, under, over) => {
284
+ const clampMin = v === 'min';
285
+ const clampMax = v === 'max';
286
+ const value = v === 'top' || v === 'left' || v === 'start' || clampMin ? 0 :
287
+ v === 'bottom' || v === 'right' || v === 'end' || clampMax ? '100%' :
288
+ v === 'center' ? '50%' :
289
+ v;
290
+ const { n, u } = decomposeRawValue(value, decomposedOriginalValue);
291
+ let px = n;
292
+ if (u === '%') {
293
+ px = (n / 100) * size;
294
+ } else if (u) {
295
+ px = convertValueUnit($el, decomposedOriginalValue, 'px', true).n;
296
+ }
297
+ if (clampMax && under < 0) px += under;
298
+ if (clampMin && over > 0) px += over;
299
+ return px;
300
+ };
301
+
302
+ /**
303
+ * @param {HTMLElement} $el
304
+ * @param {ScrollThresholdValue} v
305
+ * @param {Number} size
306
+ * @param {Number} [under]
307
+ * @param {Number} [over]
308
+ * @return {Number}
309
+ */
310
+ const parseBoundValue = ($el, v, size, under, over) => {
311
+ /** @type {Number} */
312
+ let value;
313
+ if (isStr(v)) {
314
+ const matchedOperator = relativeValuesExecRgx.exec(/** @type {String} */(v));
315
+ if (matchedOperator) {
316
+ const splitter = matchedOperator[0];
317
+ const operator = splitter[0];
318
+ const splitted = /** @type {String} */(v).split(splitter);
319
+ const clampMin = splitted[0] === 'min';
320
+ const clampMax = splitted[0] === 'max';
321
+ const valueAPx = convertValueToPx($el, splitted[0], size, under, over);
322
+ const valueBPx = convertValueToPx($el, splitted[1], size, under, over);
323
+ if (clampMin) {
324
+ const min = getRelativeValue(convertValueToPx($el, 'min', size), valueBPx, operator);
325
+ value = min < valueAPx ? valueAPx : min;
326
+ } else if (clampMax) {
327
+ const max = getRelativeValue(convertValueToPx($el, 'max', size), valueBPx, operator);
328
+ value = max > valueAPx ? valueAPx : max;
329
+ } else {
330
+ value = getRelativeValue(valueAPx, valueBPx, operator);
331
+ }
332
+ } else {
333
+ value = convertValueToPx($el, v, size, under, over);
334
+ }
335
+ } else {
336
+ value = /** @type {Number} */(v);
337
+ }
338
+ return round(value, 0);
339
+ };
340
+
341
+ /**
342
+ * @param {JSAnimation} linked
343
+ * @return {HTMLElement}
344
+ */
345
+ const getAnimationDomTarget = linked => {
346
+ let $linkedTarget;
347
+ const linkedTargets = linked.targets;
348
+ for (let i = 0, l = linkedTargets.length; i < l; i++) {
349
+ const target = linkedTargets[i];
350
+ if (target[isDomSymbol]) {
351
+ $linkedTarget = /** @type {HTMLElement} */(target);
352
+ break;
353
+ }
354
+ }
355
+ return $linkedTarget;
356
+ };
357
+
358
+ let scrollerIndex = 0;
359
+
360
+ const debugColors = ['#FF4B4B','#FF971B','#FFC730','#F9F640','#7AFF5A','#18FF74','#17E09B','#3CFFEC','#05DBE9','#33B3F1','#638CF9','#C563FE','#FF4FCF','#F93F8A'];
361
+
362
+ class ScrollObserver {
363
+ /**
364
+ * @param {ScrollObserverParams} parameters
365
+ */
366
+ constructor(parameters = {}) {
367
+ if (scope.current) scope.current.register(this);
368
+ const syncMode = setValue(parameters.sync, 'play pause');
369
+ const ease = syncMode ? parseEase(/** @type {EasingParam} */(syncMode)) : null;
370
+ const isLinear = syncMode && (syncMode === 'linear' || syncMode === none);
371
+ const isEase = syncMode && !(ease === none && !isLinear);
372
+ const isSmooth = syncMode && (isNum(syncMode) || syncMode === true || isLinear);
373
+ const isMethods = syncMode && (isStr(syncMode) && !isEase && !isSmooth);
374
+ const syncMethods = isMethods ? /** @type {String} */(syncMode).split(' ').map(
375
+ (/** @type {String} */m) => () => {
376
+ const linked = this.linked;
377
+ return linked && linked[m] ? linked[m]() : null;
378
+ }
379
+ ) : null;
380
+ const biDirSync = isMethods && syncMethods.length > 2;
381
+ /** @type {Number} */
382
+ this.index = scrollerIndex++;
383
+ /** @type {String|Number} */
384
+ this.id = !isUnd(parameters.id) ? parameters.id : this.index;
385
+ /** @type {ScrollContainer} */
386
+ this.container = registerAndGetScrollContainer(parameters.container);
387
+ /** @type {HTMLElement} */
388
+ this.target = null;
389
+ /** @type {Tickable|WAAPIAnimation} */
390
+ this.linked = null;
391
+ /** @type {Boolean} */
392
+ this.repeat = null;
393
+ /** @type {Boolean} */
394
+ this.horizontal = null;
395
+ /** @type {ScrollThresholdParam|ScrollThresholdValue|ScrollThresholdCallback} */
396
+ this.enter = null;
397
+ /** @type {ScrollThresholdParam|ScrollThresholdValue|ScrollThresholdCallback} */
398
+ this.leave = null;
399
+ /** @type {Boolean} */
400
+ this.sync = isEase || isSmooth || !!syncMethods;
401
+ /** @type {EasingFunction} */
402
+ this.syncEase = isEase ? ease : null;
403
+ /** @type {Number} */
404
+ this.syncSmooth = isSmooth ? syncMode === true || isLinear ? 1 : /** @type {Number} */(syncMode) : null;
405
+ /** @type {Callback<ScrollObserver>} */
406
+ this.onSyncEnter = syncMethods && !biDirSync && syncMethods[0] ? syncMethods[0] : noop;
407
+ /** @type {Callback<ScrollObserver>} */
408
+ this.onSyncLeave = syncMethods && !biDirSync && syncMethods[1] ? syncMethods[1] : noop;
409
+ /** @type {Callback<ScrollObserver>} */
410
+ this.onSyncEnterForward = syncMethods && biDirSync && syncMethods[0] ? syncMethods[0] : noop;
411
+ /** @type {Callback<ScrollObserver>} */
412
+ this.onSyncLeaveForward = syncMethods && biDirSync && syncMethods[1] ? syncMethods[1] : noop;
413
+ /** @type {Callback<ScrollObserver>} */
414
+ this.onSyncEnterBackward = syncMethods && biDirSync && syncMethods[2] ? syncMethods[2] : noop;
415
+ /** @type {Callback<ScrollObserver>} */
416
+ this.onSyncLeaveBackward = syncMethods && biDirSync && syncMethods[3] ? syncMethods[3] : noop;
417
+ /** @type {Callback<ScrollObserver>} */
418
+ this.onEnter = parameters.onEnter || noop;
419
+ /** @type {Callback<ScrollObserver>} */
420
+ this.onLeave = parameters.onLeave || noop;
421
+ /** @type {Callback<ScrollObserver>} */
422
+ this.onEnterForward = parameters.onEnterForward || noop;
423
+ /** @type {Callback<ScrollObserver>} */
424
+ this.onLeaveForward = parameters.onLeaveForward || noop;
425
+ /** @type {Callback<ScrollObserver>} */
426
+ this.onEnterBackward = parameters.onEnterBackward || noop;
427
+ /** @type {Callback<ScrollObserver>} */
428
+ this.onLeaveBackward = parameters.onLeaveBackward || noop;
429
+ /** @type {Callback<ScrollObserver>} */
430
+ this.onUpdate = parameters.onUpdate || noop;
431
+ /** @type {Callback<ScrollObserver>} */
432
+ this.onSyncComplete = parameters.onSyncComplete || noop;
433
+ /** @type {Boolean} */
434
+ this.reverted = false;
435
+ /** @type {Boolean} */
436
+ this.completed = false;
437
+ /** @type {Boolean} */
438
+ this.began = false;
439
+ /** @type {Boolean} */
440
+ this.isInView = false;
441
+ /** @type {Boolean} */
442
+ this.forceEnter = false;
443
+ /** @type {Boolean} */
444
+ this.hasEntered = false;
445
+ // /** @type {Array.<Number>} */
446
+ // this.offsets = [];
447
+ /** @type {Number} */
448
+ this.offset = 0;
449
+ /** @type {Number} */
450
+ this.offsetStart = 0;
451
+ /** @type {Number} */
452
+ this.offsetEnd = 0;
453
+ /** @type {Number} */
454
+ this.distance = 0;
455
+ /** @type {Number} */
456
+ this.prevProgress = 0;
457
+ /** @type {Array} */
458
+ this.thresholds = ['start', 'end', 'end', 'start'];
459
+ /** @type {[Number, Number, Number, Number]} */
460
+ this.coords = [0, 0, 0, 0];
461
+ /** @type {JSAnimation} */
462
+ this.debugStyles = null;
463
+ /** @type {HTMLElement} */
464
+ this.$debug = null;
465
+ /** @type {ScrollObserverParams} */
466
+ this._params = parameters;
467
+ /** @type {Boolean} */
468
+ this._debug = setValue(parameters.debug, false);
469
+ /** @type {ScrollObserver} */
470
+ this._next = null;
471
+ /** @type {ScrollObserver} */
472
+ this._prev = null;
473
+ addChild(this.container, this);
474
+ // Wait for the next frame to add to the container in order to handle calls to link()
475
+ sync(() => {
476
+ if (this.reverted) return;
477
+ if (!this.target) {
478
+ const target = /** @type {HTMLElement} */(parseTargets(parameters.target)[0]);
479
+ this.target = target || doc.body;
480
+ this.refresh();
481
+ }
482
+ if (this._debug) this.debug();
483
+ });
484
+ }
485
+
486
+ /**
487
+ * @param {Tickable|WAAPIAnimation} linked
488
+ */
489
+ link(linked) {
490
+ if (linked) {
491
+ // Make sure to pause the linked object in case it's added later
492
+ linked.pause();
493
+ this.linked = linked;
494
+ // Try to use a target of the linked object if no target parameters specified
495
+ if (!this._params.target) {
496
+ /** @type {HTMLElement} */
497
+ let $linkedTarget;
498
+ if (!isUnd(/** @type {JSAnimation} */(linked).targets)) {
499
+ $linkedTarget = getAnimationDomTarget(/** @type {JSAnimation} */(linked));
500
+ } else {
501
+ forEachChildren(/** @type {Timeline} */(linked), (/** @type {JSAnimation} */child) => {
502
+ if (child.targets && !$linkedTarget) {
503
+ $linkedTarget = getAnimationDomTarget(/** @type {JSAnimation} */(child));
504
+ }
505
+ });
506
+ }
507
+ // Fallback to body if no target found
508
+ this.target = $linkedTarget || doc.body;
509
+ this.refresh();
510
+ }
511
+ }
512
+ return this;
513
+ }
514
+
515
+ get velocity() {
516
+ return this.container.velocity;
517
+ }
518
+
519
+ get backward() {
520
+ return this.horizontal ? this.container.backwardX : this.container.backwardY;
521
+ }
522
+
523
+ get scroll() {
524
+ return this.horizontal ? this.container.scrollX : this.container.scrollY;
525
+ }
526
+
527
+ get progress() {
528
+ const p = (this.scroll - this.offsetStart) / this.distance;
529
+ return p === Infinity || isNaN(p) ? 0 : round(clamp(p, 0, 1), 6);
530
+ }
531
+
532
+ refresh() {
533
+ this.reverted = false;
534
+ const params = this._params;
535
+ this.repeat = setValue(parseScrollObserverFunctionParameter(params.repeat, this), true);
536
+ this.horizontal = setValue(parseScrollObserverFunctionParameter(params.axis, this), 'y') === 'x';
537
+ this.enter = setValue(parseScrollObserverFunctionParameter(params.enter, this), 'end start');
538
+ this.leave = setValue(parseScrollObserverFunctionParameter(params.leave, this), 'start end');
539
+ this.updateBounds();
540
+ this.handleScroll();
541
+ return this;
542
+ }
543
+
544
+ removeDebug() {
545
+ if (this.$debug) {
546
+ this.$debug.parentNode.removeChild(this.$debug);
547
+ this.$debug = null;
548
+ }
549
+ if (this.debugStyles) {
550
+ this.debugStyles.revert();
551
+ this.$debug = null;
552
+ }
553
+ return this;
554
+ }
555
+
556
+ debug() {
557
+ this.removeDebug();
558
+ const container = this.container;
559
+ const isHori = this.horizontal;
560
+ const $existingDebug = container.element.querySelector(':scope > .animejs-onscroll-debug');
561
+ const $debug = doc.createElement('div');
562
+ const $thresholds = doc.createElement('div');
563
+ const $triggers = doc.createElement('div');
564
+ const color = debugColors[this.index % debugColors.length];
565
+ const useWin = container.useWin;
566
+ const containerWidth = useWin ? container.winWidth : container.width;
567
+ const containerHeight = useWin ? container.winHeight : container.height;
568
+ const scrollWidth = container.scrollWidth;
569
+ const scrollHeight = container.scrollHeight;
570
+ const size = this.container.width > 360 ? 320 : 260;
571
+ const offLeft = isHori ? 0 : 10;
572
+ const offTop = isHori ? 10 : 0;
573
+ const half = isHori ? 24 : size / 2;
574
+ const labelHeight = isHori ? half : 15;
575
+ const labelWidth = isHori ? 60 : half;
576
+ const labelSize = isHori ? labelWidth : labelHeight;
577
+ const repeat = isHori ? 'repeat-x' : 'repeat-y';
578
+ /**
579
+ * @param {Number} v
580
+ * @return {String}
581
+ */
582
+ const gradientOffset = v => isHori ? '0px '+(v)+'px' : (v)+'px'+' 2px';
583
+ /**
584
+ * @param {String} c
585
+ * @return {String}
586
+ */
587
+ const lineCSS = (c) => `linear-gradient(${isHori ? 90 : 0}deg, ${c} 2px, transparent 1px)`;
588
+ /**
589
+ * @param {String} p
590
+ * @param {Number} l
591
+ * @param {Number} t
592
+ * @param {Number} w
593
+ * @param {Number} h
594
+ * @return {String}
595
+ */
596
+ const baseCSS = (p, l, t, w, h) => `position:${p};left:${l}px;top:${t}px;width:${w}px;height:${h}px;`;
597
+ $debug.style.cssText = `${baseCSS('absolute', offLeft, offTop, isHori ? scrollWidth : size, isHori ? size : scrollHeight)}
598
+ pointer-events: none;
599
+ z-index: ${this.container.zIndex++};
600
+ display: flex;
601
+ flex-direction: ${isHori ? 'column' : 'row'};
602
+ filter: drop-shadow(0px 1px 0px rgba(0,0,0,.75));
603
+ `;
604
+ $thresholds.style.cssText = `${baseCSS('sticky', 0, 0, isHori ? containerWidth : half, isHori ? half : containerHeight)}`;
605
+ if (!$existingDebug) {
606
+ $thresholds.style.cssText += `background:
607
+ ${lineCSS('#FFFF')}${gradientOffset(half-10)} / ${isHori ? '100px 100px' : '100px 100px'} ${repeat},
608
+ ${lineCSS('#FFF8')}${gradientOffset(half-10)} / ${isHori ? '10px 10px' : '10px 10px'} ${repeat};
609
+ `;
610
+ }
611
+ $triggers.style.cssText = `${baseCSS('relative', 0, 0, isHori ? scrollWidth : half, isHori ? half : scrollHeight)}`;
612
+ if (!$existingDebug) {
613
+ $triggers.style.cssText += `background:
614
+ ${lineCSS('#FFFF')}${gradientOffset(0)} / ${isHori ? '100px 10px' : '10px 100px'} ${repeat},
615
+ ${lineCSS('#FFF8')}${gradientOffset(0)} / ${isHori ? '10px 0px' : '0px 10px'} ${repeat};
616
+ `;
617
+ }
618
+ const labels = [' enter: ', ' leave: '];
619
+ this.coords.forEach((v, i) => {
620
+ const isView = i > 1;
621
+ const value = (isView ? 0 : this.offset) + v;
622
+ const isTail = i % 2;
623
+ const isFirst = value < labelSize;
624
+ const isOver = value > (isView ? isHori ? containerWidth : containerHeight : isHori ? scrollWidth : scrollHeight) - labelSize;
625
+ const isFlip = (isView ? isTail && !isFirst : !isTail && !isFirst) || isOver;
626
+ const $label = doc.createElement('div');
627
+ const $text = doc.createElement('div');
628
+ const dirProp = isHori ? isFlip ? 'right' : 'left' : isFlip ? 'bottom' : 'top';
629
+ const flipOffset = isFlip ? (isHori ? labelWidth : labelHeight) + (!isView ? isHori ? -1 : -2 : isHori ? -1 : isOver ? 0 : -2) : !isView ? isHori ? 1 : 0 : isHori ? 1 : 0;
630
+ // $text.innerHTML = `${!isView ? '' : labels[isTail] + ' '}${this.id}: ${this.thresholds[i]} ${isView ? '' : labels[isTail]}`;
631
+ $text.innerHTML = `${this.id}${labels[isTail]}${this.thresholds[i]}`;
632
+ $label.style.cssText = `${baseCSS('absolute', 0, 0, labelWidth, labelHeight)}
633
+ display: flex;
634
+ flex-direction: ${isHori ? 'column' : 'row'};
635
+ justify-content: flex-${isView ? 'start' : 'end'};
636
+ align-items: flex-${isFlip ? 'end' : 'start'};
637
+ border-${dirProp}: 2px ${isTail ? 'solid' : 'solid'} ${color};
638
+ `;
639
+ $text.style.cssText = `
640
+ overflow: hidden;
641
+ max-width: ${(size / 2) - 10}px;
642
+ height: ${labelHeight};
643
+ margin-${isHori ? isFlip ? 'right' : 'left' : isFlip ? 'bottom' : 'top'}: -2px;
644
+ padding: 1px;
645
+ font-family: ui-monospace, monospace;
646
+ font-size: 10px;
647
+ letter-spacing: -.025em;
648
+ line-height: 9px;
649
+ font-weight: 600;
650
+ text-align: ${isHori && isFlip || !isHori && !isView ? 'right' : 'left'};
651
+ white-space: pre;
652
+ text-overflow: ellipsis;
653
+ color: ${isTail ? color : 'rgba(0,0,0,.75)'};
654
+ background-color: ${isTail ? 'rgba(0,0,0,.65)' : color};
655
+ border: 2px solid ${isTail ? color : 'transparent'};
656
+ border-${isHori ? isFlip ? 'top-left' : 'top-right' : isFlip ? 'top-left' : 'bottom-left'}-radius: 5px;
657
+ border-${isHori ? isFlip ? 'bottom-left' : 'bottom-right' : isFlip ? 'top-right' : 'bottom-right'}-radius: 5px;
658
+ `;
659
+ $label.appendChild($text);
660
+ let position = value - flipOffset + (isHori ? 1 : 0);
661
+ $label.style[isHori ? 'left' : 'top'] = `${position}px`;
662
+ // $label.style[isHori ? 'left' : 'top'] = value - flipOffset + (!isFlip && isFirst && !isView ? 1 : isFlip ? 0 : -2) + 'px';
663
+ (isView ? $thresholds : $triggers).appendChild($label);
664
+ });
665
+
666
+ $debug.appendChild($thresholds);
667
+ $debug.appendChild($triggers);
668
+ container.element.appendChild($debug);
669
+
670
+ if (!$existingDebug) $debug.classList.add('animejs-onscroll-debug');
671
+ this.$debug = $debug;
672
+ const containerPosition = get(container.element, 'position');
673
+ if (containerPosition === 'static') {
674
+ this.debugStyles = set(container.element, { position: 'relative '});
675
+ }
676
+
677
+ }
678
+
679
+ updateBounds() {
680
+ if (this._debug) {
681
+ this.removeDebug();
682
+ }
683
+ let stickys;
684
+ const $target = this.target;
685
+ const container = this.container;
686
+ const isHori = this.horizontal;
687
+ const linked = this.linked;
688
+ let linkedTime;
689
+ let $el = $target;
690
+ // let offsetX = 0;
691
+ // let offsetY = 0;
692
+ // let $offsetParent = $el;
693
+ /** @type {Element} */
694
+ if (linked) {
695
+ linkedTime = linked.currentTime;
696
+ linked.seek(0, true);
697
+ }
698
+ /* Old implementation to get offset and targetSize before fixing https://github.com/juliangarnier/anime/issues/1021
699
+ // const isContainerStatic = get(container.element, 'position') === 'static' ? set(container.element, { position: 'relative '}) : false;
700
+ // while ($el && $el !== container.element && $el !== doc.body) {
701
+ // const isSticky = get($el, 'position') === 'sticky' ?
702
+ // set($el, { position: 'static' }) :
703
+ // false;
704
+ // if ($el === $offsetParent) {
705
+ // offsetX += $el.offsetLeft || 0;
706
+ // offsetY += $el.offsetTop || 0;
707
+ // $offsetParent = $el.offsetParent;
708
+ // }
709
+ // $el = /** @type {HTMLElement} */($el.parentElement);
710
+ // if (isSticky) {
711
+ // if (!stickys) stickys = [];
712
+ // stickys.push(isSticky);
713
+ // }
714
+ // }
715
+ // if (isContainerStatic) isContainerStatic.revert();
716
+ // const offset = isHori ? offsetX : offsetY;
717
+ // const targetSize = isHori ? $target.offsetWidth : $target.offsetHeight;
718
+
719
+ while ($el && $el !== container.element && $el !== doc.body) {
720
+ const isSticky = get($el, 'position') === 'sticky' ? set($el, { position: 'static' }) : false;
721
+ $el = $el.parentElement;
722
+ if (isSticky) {
723
+ if (!stickys) stickys = [];
724
+ stickys.push(isSticky);
725
+ }
726
+ }
727
+ const rect = $target.getBoundingClientRect();
728
+ const offset = isHori ? rect.left + container.scrollX - container.left : rect.top + container.scrollY - container.top;
729
+ const targetSize = isHori ? rect.width : rect.height;
730
+ const containerSize = isHori ? container.width : container.height;
731
+ const scrollSize = isHori ? container.scrollWidth : container.scrollHeight;
732
+ const maxScroll = scrollSize - containerSize;
733
+ const enter = this.enter;
734
+ const leave = this.leave;
735
+
736
+ /** @type {ScrollThresholdValue} */
737
+ let enterTarget = 'start';
738
+ /** @type {ScrollThresholdValue} */
739
+ let leaveTarget = 'end';
740
+ /** @type {ScrollThresholdValue} */
741
+ let enterContainer = 'end';
742
+ /** @type {ScrollThresholdValue} */
743
+ let leaveContainer = 'start';
744
+
745
+ if (isStr(enter)) {
746
+ const splitted = /** @type {String} */(enter).split(' ');
747
+ enterContainer = splitted[0];
748
+ enterTarget = splitted.length > 1 ? splitted[1] : enterTarget;
749
+ } else if (isObj(enter)) {
750
+ const e = /** @type {ScrollThresholdParam} */(enter);
751
+ if (!isUnd(e.container)) enterContainer = e.container;
752
+ if (!isUnd(e.target)) enterTarget = e.target;
753
+ } else if (isNum(enter)) {
754
+ enterContainer = /** @type {Number} */(enter);
755
+ }
756
+
757
+ if (isStr(leave)) {
758
+ const splitted = /** @type {String} */(leave).split(' ');
759
+ leaveContainer = splitted[0];
760
+ leaveTarget = splitted.length > 1 ? splitted[1] : leaveTarget;
761
+ } else if (isObj(leave)) {
762
+ const t = /** @type {ScrollThresholdParam} */(leave);
763
+ if (!isUnd(t.container)) leaveContainer = t.container;
764
+ if (!isUnd(t.target)) leaveTarget = t.target;
765
+ } else if (isNum(leave)) {
766
+ leaveContainer = /** @type {Number} */(leave);
767
+ }
768
+
769
+ const parsedEnterTarget = parseBoundValue($target, enterTarget, targetSize);
770
+ const parsedLeaveTarget = parseBoundValue($target, leaveTarget, targetSize);
771
+ const under = (parsedEnterTarget + offset) - containerSize;
772
+ const over = (parsedLeaveTarget + offset) - maxScroll;
773
+ const parsedEnterContainer = parseBoundValue($target, enterContainer, containerSize, under, over);
774
+ const parsedLeaveContainer = parseBoundValue($target, leaveContainer, containerSize, under, over);
775
+ const offsetStart = parsedEnterTarget + offset - parsedEnterContainer;
776
+ const offsetEnd = parsedLeaveTarget + offset - parsedLeaveContainer;
777
+ const scrollDelta = offsetEnd - offsetStart;
778
+ // this.offsets[0] = offsetX;
779
+ // this.offsets[1] = offsetY;
780
+ this.offset = offset;
781
+ this.offsetStart = offsetStart;
782
+ this.offsetEnd = offsetEnd;
783
+ this.distance = scrollDelta <= 0 ? 0 : scrollDelta;
784
+ this.thresholds = [enterTarget, leaveTarget, enterContainer, leaveContainer];
785
+ this.coords = [parsedEnterTarget, parsedLeaveTarget, parsedEnterContainer, parsedLeaveContainer];
786
+ if (stickys) {
787
+ stickys.forEach(sticky => sticky.revert());
788
+ }
789
+ if (linked) {
790
+ linked.seek(linkedTime, true);
791
+ }
792
+ if (this._debug) {
793
+ this.debug();
794
+ }
795
+ }
796
+
797
+ handleScroll() {
798
+ const linked = this.linked;
799
+ const sync = this.sync;
800
+ const syncEase = this.syncEase;
801
+ const syncSmooth = this.syncSmooth;
802
+ const shouldSeek = linked && (syncEase || syncSmooth);
803
+ const isHori = this.horizontal;
804
+ const container = this.container;
805
+ const scroll = this.scroll;
806
+ const isBefore = scroll <= this.offsetStart;
807
+ const isAfter = scroll >= this.offsetEnd;
808
+ const isInView = !isBefore && !isAfter;
809
+ const isOnTheEdge = scroll === this.offsetStart || scroll === this.offsetEnd;
810
+ const forceEnter = !this.hasEntered && isOnTheEdge;
811
+ const $debug = this._debug && this.$debug;
812
+ let hasUpdated = false;
813
+ let syncCompleted = false;
814
+ let p = this.progress;
815
+
816
+ if (isBefore && this.began) {
817
+ this.began = false;
818
+ }
819
+
820
+ if (p > 0 && !this.began) {
821
+ this.began = true;
822
+ }
823
+
824
+ if (shouldSeek) {
825
+ const lp = linked.progress;
826
+ if (syncSmooth && isNum(syncSmooth)) {
827
+ if (/** @type {Number} */(syncSmooth) < 1) {
828
+ const step = 0.0001;
829
+ const snap = lp < p && p === 1 ? step : lp > p && !p ? -step : 0;
830
+ p = round(lerp(lp, p, lerp(.01, .2, /** @type {Number} */(syncSmooth))) + snap, 6);
831
+ }
832
+ } else if (syncEase) {
833
+ p = syncEase(p);
834
+ }
835
+ hasUpdated = p !== this.prevProgress;
836
+ syncCompleted = lp === 1;
837
+ if (hasUpdated && !syncCompleted && (syncSmooth && lp)) {
838
+ container.wakeTicker.restart();
839
+ }
840
+ }
841
+
842
+ if ($debug) {
843
+ const sticky = isHori ? container.scrollY : container.scrollX;
844
+ $debug.style[isHori ? 'top' : 'left'] = sticky + 10 + 'px';
845
+ }
846
+
847
+ // Trigger enter callbacks if already in view or when entering the view
848
+ if ((isInView && !this.isInView) || (forceEnter && !this.forceEnter && !this.hasEntered)) {
849
+ if (isInView) this.isInView = true;
850
+ if (!this.forceEnter || !this.hasEntered) {
851
+ if ($debug && isInView) $debug.style.zIndex = `${this.container.zIndex++}`;
852
+ this.onSyncEnter(this);
853
+ this.onEnter(this);
854
+ if (this.backward) {
855
+ this.onSyncEnterBackward(this);
856
+ this.onEnterBackward(this);
857
+ } else {
858
+ this.onSyncEnterForward(this);
859
+ this.onEnterForward(this);
860
+ }
861
+ this.hasEntered = true;
862
+ if (forceEnter) this.forceEnter = true;
863
+ } else if (isInView) {
864
+ this.forceEnter = false;
865
+ }
866
+ }
867
+
868
+ if (isInView || !isInView && this.isInView) {
869
+ hasUpdated = true;
870
+ }
871
+
872
+ if (hasUpdated) {
873
+ if (shouldSeek) linked.seek(linked.duration * p);
874
+ this.onUpdate(this);
875
+ }
876
+
877
+ if (!isInView && this.isInView) {
878
+ this.isInView = false;
879
+ this.onSyncLeave(this);
880
+ this.onLeave(this);
881
+ if (this.backward) {
882
+ this.onSyncLeaveBackward(this);
883
+ this.onLeaveBackward(this);
884
+ } else {
885
+ this.onSyncLeaveForward(this);
886
+ this.onLeaveForward(this);
887
+ }
888
+ if (sync && !syncSmooth) {
889
+ syncCompleted = true;
890
+ }
891
+ }
892
+
893
+ if (p >= 1 && this.began && !this.completed && (sync && syncCompleted || !sync)) {
894
+ if (sync) {
895
+ this.onSyncComplete(this);
896
+ }
897
+ this.completed = true;
898
+ if ((!this.repeat && !linked) || (!this.repeat && linked && linked.completed)) {
899
+ this.revert();
900
+ }
901
+ }
902
+
903
+ if (p < 1 && this.completed) {
904
+ this.completed = false;
905
+ }
906
+
907
+ this.prevProgress = p;
908
+ }
909
+
910
+ revert() {
911
+ if (this.reverted) return;
912
+ const container = this.container;
913
+ removeChild(container, this);
914
+ if (!container._head) {
915
+ container.revert();
916
+ }
917
+ if (this._debug) {
918
+ this.removeDebug();
919
+ }
920
+ this.reverted = true;
921
+ return this;
922
+ }
923
+
924
+ }
925
+
926
+ /**
927
+ * @param {ScrollObserverParams} [parameters={}]
928
+ * @return {ScrollObserver}
929
+ */
930
+ const onScroll = (parameters = {}) => new ScrollObserver(parameters);
931
+
932
+ export { ScrollObserver, onScroll, scrollContainers };