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