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,1223 @@
1
+ /**
2
+ * Anime.js - draggable - ESM
3
+ * @version v4.2.0
4
+ * @license MIT
5
+ * @copyright 2025 - Julian Garnier
6
+ */
7
+
8
+ import { globals, scope } from '../core/globals.js';
9
+ import { doc, win, noop, maxValue, compositionTypes } from '../core/consts.js';
10
+ import { parseTargets } from '../core/targets.js';
11
+ import { isUnd, isObj, isArr, now, atan2, round, max, snap, clamp, abs, sqrt, cos, sin, isFnc } from '../core/helpers.js';
12
+ import { setValue } from '../core/values.js';
13
+ import { mapRange } from '../utils/number.js';
14
+ import { Timer } from '../timer/timer.js';
15
+ import { JSAnimation } from '../animation/animation.js';
16
+ import { removeTargetsFromRenderable } from '../animation/composition.js';
17
+ import { Animatable } from '../animatable/animatable.js';
18
+ import { parseEase, eases } from '../easings/eases.js';
19
+ import { createSpring } from '../spring/spring.js';
20
+ import { get, set } from '../utils/target.js';
21
+
22
+ /**
23
+ * @import {
24
+ * DOMTarget,
25
+ * DOMTargetSelector,
26
+ * DraggableCursorParams,
27
+ * TargetsParam,
28
+ * DraggableParams,
29
+ * EasingFunction,
30
+ * Callback,
31
+ * AnimatableParams,
32
+ * DraggableAxisParam,
33
+ * AnimatableObject,
34
+ * EasingParam,
35
+ * } from '../types/index.js'
36
+ */
37
+
38
+ /**
39
+ * @import {
40
+ * Spring,
41
+ * } from '../spring/spring.js'
42
+ */
43
+
44
+ /**
45
+ * @param {Event} e
46
+ */
47
+ const preventDefault = e => {
48
+ if (e.cancelable) e.preventDefault();
49
+ };
50
+
51
+ class DOMProxy {
52
+ /** @param {Object} el */
53
+ constructor(el) {
54
+ this.el = el;
55
+ this.zIndex = 0;
56
+ this.parentElement = null;
57
+ this.classList = {
58
+ add: noop,
59
+ remove: noop,
60
+ };
61
+ }
62
+
63
+ get x() { return this.el.x || 0 };
64
+ set x(v) { this.el.x = v; };
65
+
66
+ get y() { return this.el.y || 0 };
67
+ set y(v) { this.el.y = v; };
68
+
69
+ get width() { return this.el.width || 0 };
70
+ set width(v) { this.el.width = v; };
71
+
72
+ get height() { return this.el.height || 0 };
73
+ set height(v) { this.el.height = v; };
74
+
75
+ getBoundingClientRect() {
76
+ return {
77
+ top: this.y,
78
+ right: this.x,
79
+ bottom: this.y + this.height,
80
+ left: this.x + this.width,
81
+ }
82
+ }
83
+ }
84
+
85
+ class Transforms {
86
+ /**
87
+ * @param {DOMTarget|DOMProxy} $el
88
+ */
89
+ constructor($el) {
90
+ this.$el = $el;
91
+ this.inlineTransforms = [];
92
+ this.point = new DOMPoint();
93
+ this.inversedMatrix = this.getMatrix().inverse();
94
+ }
95
+
96
+ /**
97
+ * @param {Number} x
98
+ * @param {Number} y
99
+ * @return {DOMPoint}
100
+ */
101
+ normalizePoint(x, y) {
102
+ this.point.x = x;
103
+ this.point.y = y;
104
+ return this.point.matrixTransform(this.inversedMatrix);
105
+ }
106
+
107
+ /**
108
+ * @callback TraverseParentsCallback
109
+ * @param {DOMTarget} $el
110
+ * @param {Number} i
111
+ */
112
+
113
+ /**
114
+ * @param {TraverseParentsCallback} cb
115
+ */
116
+ traverseUp(cb) {
117
+ let $el = /** @type {DOMTarget|Document} */(this.$el.parentElement), i = 0;
118
+ while ($el && $el !== doc) {
119
+ cb(/** @type {DOMTarget} */($el), i);
120
+ $el = /** @type {DOMTarget} */($el.parentElement);
121
+ i++;
122
+ }
123
+ }
124
+
125
+ getMatrix() {
126
+ const matrix = new DOMMatrix();
127
+ this.traverseUp($el => {
128
+ const transformValue = getComputedStyle($el).transform;
129
+ if (transformValue) {
130
+ const elMatrix = new DOMMatrix(transformValue);
131
+ matrix.preMultiplySelf(elMatrix);
132
+ }
133
+ });
134
+ return matrix;
135
+ }
136
+
137
+ remove() {
138
+ this.traverseUp(($el, i) => {
139
+ this.inlineTransforms[i] = $el.style.transform;
140
+ $el.style.transform = 'none';
141
+ });
142
+ }
143
+
144
+ revert() {
145
+ this.traverseUp(($el, i) => {
146
+ const ct = this.inlineTransforms[i];
147
+ if (ct === '') {
148
+ $el.style.removeProperty('transform');
149
+ } else {
150
+ $el.style.transform = ct;
151
+ }
152
+ });
153
+ }
154
+ }
155
+
156
+ /**
157
+ * @template {Array<Number>|DOMTargetSelector|String|Number|Boolean|Function|DraggableCursorParams} T
158
+ * @param {T | ((draggable: Draggable) => T)} value
159
+ * @param {Draggable} draggable
160
+ * @return {T}
161
+ */
162
+ const parseDraggableFunctionParameter = (value, draggable) => value && isFnc(value) ? /** @type {Function} */(value)(draggable) : /** @type {T} */(value);
163
+
164
+ let zIndex = 0;
165
+
166
+ class Draggable {
167
+ /**
168
+ * @param {TargetsParam} target
169
+ * @param {DraggableParams} [parameters]
170
+ */
171
+ constructor(target, parameters = {}) {
172
+ if (!target) return;
173
+ if (scope.current) scope.current.register(this);
174
+ const paramX = parameters.x;
175
+ const paramY = parameters.y;
176
+ const trigger = parameters.trigger;
177
+ const modifier = parameters.modifier;
178
+ const ease = parameters.releaseEase;
179
+ const customEase = ease && parseEase(ease);
180
+ const hasSpring = !isUnd(ease) && !isUnd(/** @type {Spring} */(ease).ease);
181
+ const xProp = /** @type {String} */(isObj(paramX) && !isUnd(/** @type {Object} */(paramX).mapTo) ? /** @type {Object} */(paramX).mapTo : 'translateX');
182
+ const yProp = /** @type {String} */(isObj(paramY) && !isUnd(/** @type {Object} */(paramY).mapTo) ? /** @type {Object} */(paramY).mapTo : 'translateY');
183
+ const container = parseDraggableFunctionParameter(parameters.container, this);
184
+ this.containerArray = isArr(container) ? container : null;
185
+ this.$container = /** @type {HTMLElement} */(container && !this.containerArray ? parseTargets(/** @type {DOMTarget} */(container))[0] : doc.body);
186
+ this.useWin = this.$container === doc.body;
187
+ /** @type {Window | HTMLElement} */
188
+ this.$scrollContainer = this.useWin ? win : this.$container;
189
+ this.$target = /** @type {HTMLElement} */(isObj(target) ? new DOMProxy(target) : parseTargets(target)[0]);
190
+ this.$trigger = /** @type {HTMLElement} */(parseTargets(trigger ? trigger : target)[0]);
191
+ this.fixed = get(this.$target, 'position') === 'fixed';
192
+ // Refreshable parameters
193
+ this.isFinePointer = true;
194
+ /** @type {[Number, Number, Number, Number]} */
195
+ this.containerPadding = [0, 0, 0, 0];
196
+ /** @type {Number} */
197
+ this.containerFriction = 0;
198
+ /** @type {Number} */
199
+ this.releaseContainerFriction = 0;
200
+ /** @type {Number|Array<Number>} */
201
+ this.snapX = 0;
202
+ /** @type {Number|Array<Number>} */
203
+ this.snapY = 0;
204
+ /** @type {Number} */
205
+ this.scrollSpeed = 0;
206
+ /** @type {Number} */
207
+ this.scrollThreshold = 0;
208
+ /** @type {Number} */
209
+ this.dragSpeed = 0;
210
+ /** @type {Number} */
211
+ this.maxVelocity = 0;
212
+ /** @type {Number} */
213
+ this.minVelocity = 0;
214
+ /** @type {Number} */
215
+ this.velocityMultiplier = 0;
216
+ /** @type {Boolean|DraggableCursorParams} */
217
+ this.cursor = false;
218
+ /** @type {Spring} */
219
+ this.releaseXSpring = hasSpring ? /** @type {Spring} */(ease) : createSpring({
220
+ mass: setValue(parameters.releaseMass, 1),
221
+ stiffness: setValue(parameters.releaseStiffness, 80),
222
+ damping: setValue(parameters.releaseDamping, 20),
223
+ });
224
+ /** @type {Spring} */
225
+ this.releaseYSpring = hasSpring ? /** @type {Spring} */(ease) : createSpring({
226
+ mass: setValue(parameters.releaseMass, 1),
227
+ stiffness: setValue(parameters.releaseStiffness, 80),
228
+ damping: setValue(parameters.releaseDamping, 20),
229
+ });
230
+ /** @type {EasingFunction} */
231
+ this.releaseEase = customEase || eases.outQuint;
232
+ /** @type {Boolean} */
233
+ this.hasReleaseSpring = hasSpring;
234
+ /** @type {Callback<this>} */
235
+ this.onGrab = parameters.onGrab || noop;
236
+ /** @type {Callback<this>} */
237
+ this.onDrag = parameters.onDrag || noop;
238
+ /** @type {Callback<this>} */
239
+ this.onRelease = parameters.onRelease || noop;
240
+ /** @type {Callback<this>} */
241
+ this.onUpdate = parameters.onUpdate || noop;
242
+ /** @type {Callback<this>} */
243
+ this.onSettle = parameters.onSettle || noop;
244
+ /** @type {Callback<this>} */
245
+ this.onSnap = parameters.onSnap || noop;
246
+ /** @type {Callback<this>} */
247
+ this.onResize = parameters.onResize || noop;
248
+ /** @type {Callback<this>} */
249
+ this.onAfterResize = parameters.onAfterResize || noop;
250
+ /** @type {[Number, Number]} */
251
+ this.disabled = [0, 0];
252
+ /** @type {AnimatableParams} */
253
+ const animatableParams = {};
254
+ if (modifier) animatableParams.modifier = modifier;
255
+ if (isUnd(paramX) || paramX === true) {
256
+ animatableParams[xProp] = 0;
257
+ } else if (isObj(paramX)) {
258
+ const paramXObject = /** @type {DraggableAxisParam} */(paramX);
259
+ const animatableXParams = {};
260
+ if (paramXObject.modifier) animatableXParams.modifier = paramXObject.modifier;
261
+ if (paramXObject.composition) animatableXParams.composition = paramXObject.composition;
262
+ animatableParams[xProp] = animatableXParams;
263
+ } else if (paramX === false) {
264
+ animatableParams[xProp] = 0;
265
+ this.disabled[0] = 1;
266
+ }
267
+ if (isUnd(paramY) || paramY === true) {
268
+ animatableParams[yProp] = 0;
269
+ } else if (isObj(paramY)) {
270
+ const paramYObject = /** @type {DraggableAxisParam} */(paramY);
271
+ const animatableYParams = {};
272
+ if (paramYObject.modifier) animatableYParams.modifier = paramYObject.modifier;
273
+ if (paramYObject.composition) animatableYParams.composition = paramYObject.composition;
274
+ animatableParams[yProp] = animatableYParams;
275
+ } else if (paramY === false) {
276
+ animatableParams[yProp] = 0;
277
+ this.disabled[1] = 1;
278
+ }
279
+ /** @type {AnimatableObject} */
280
+ this.animate = /** @type {AnimatableObject} */(new Animatable(this.$target, animatableParams));
281
+ // Internal props
282
+ this.xProp = xProp;
283
+ this.yProp = yProp;
284
+ this.destX = 0;
285
+ this.destY = 0;
286
+ this.deltaX = 0;
287
+ this.deltaY = 0;
288
+ this.scroll = {x: 0, y: 0};
289
+ /** @type {[Number, Number, Number, Number]} */
290
+ this.coords = [this.x, this.y, 0, 0]; // x, y, temp x, temp y
291
+ /** @type {[Number, Number]} */
292
+ this.snapped = [0, 0]; // x, y
293
+ /** @type {[Number, Number, Number, Number, Number, Number, Number, Number]} */
294
+ this.pointer = [0, 0, 0, 0, 0, 0, 0, 0]; // x1, y1, x2, y2, temp x1, temp y1, temp x2, temp y2
295
+ /** @type {[Number, Number]} */
296
+ this.scrollView = [0, 0]; // w, h
297
+ /** @type {[Number, Number, Number, Number]} */
298
+ this.dragArea = [0, 0, 0, 0]; // x, y, w, h
299
+ /** @type {[Number, Number, Number, Number]} */
300
+ this.containerBounds = [-maxValue, maxValue, maxValue, -maxValue]; // t, r, b, l
301
+ /** @type {[Number, Number, Number, Number]} */
302
+ this.scrollBounds = [0, 0, 0, 0]; // t, r, b, l
303
+ /** @type {[Number, Number, Number, Number]} */
304
+ this.targetBounds = [0, 0, 0, 0]; // t, r, b, l
305
+ /** @type {[Number, Number]} */
306
+ this.window = [0, 0]; // w, h
307
+ /** @type {[Number, Number, Number]} */
308
+ this.velocityStack = [0, 0, 0];
309
+ /** @type {Number} */
310
+ this.velocityStackIndex = 0;
311
+ /** @type {Number} */
312
+ this.velocityTime = now();
313
+ /** @type {Number} */
314
+ this.velocity = 0;
315
+ /** @type {Number} */
316
+ this.angle = 0;
317
+ /** @type {JSAnimation} */
318
+ this.cursorStyles = null;
319
+ /** @type {JSAnimation} */
320
+ this.triggerStyles = null;
321
+ /** @type {JSAnimation} */
322
+ this.bodyStyles = null;
323
+ /** @type {JSAnimation} */
324
+ this.targetStyles = null;
325
+ /** @type {JSAnimation} */
326
+ this.touchActionStyles = null;
327
+ this.transforms = new Transforms(this.$target);
328
+ this.overshootCoords = { x: 0, y: 0 };
329
+ this.overshootTicker = new Timer({
330
+ autoplay: false,
331
+ onUpdate: () => {
332
+ this.updated = true;
333
+ this.manual = true;
334
+ // Use a duration of 1 to prevent the animatable from completing immediately to prevent issues with onSettle()
335
+ // https://github.com/juliangarnier/anime/issues/1045
336
+ if (!this.disabled[0]) this.animate[this.xProp](this.overshootCoords.x, 1);
337
+ if (!this.disabled[1]) this.animate[this.yProp](this.overshootCoords.y, 1);
338
+ },
339
+ onComplete: () => {
340
+ this.manual = false;
341
+ if (!this.disabled[0]) this.animate[this.xProp](this.overshootCoords.x, 0);
342
+ if (!this.disabled[1]) this.animate[this.yProp](this.overshootCoords.y, 0);
343
+ },
344
+ }, null, 0).init();
345
+ this.updateTicker = new Timer({ autoplay: false, onUpdate: () => this.update() }, null,0,).init();
346
+ this.contained = !isUnd(container);
347
+ this.manual = false;
348
+ this.grabbed = false;
349
+ this.dragged = false;
350
+ this.updated = false;
351
+ this.released = false;
352
+ this.canScroll = false;
353
+ this.enabled = false;
354
+ this.initialized = false;
355
+ this.activeProp = this.disabled[1] ? xProp : yProp;
356
+ this.animate.callbacks.onRender = () => {
357
+ const hasUpdated = this.updated;
358
+ const hasMoved = this.grabbed && hasUpdated;
359
+ const hasReleased = !hasMoved && this.released;
360
+ const x = this.x;
361
+ const y = this.y;
362
+ const dx = x - this.coords[2];
363
+ const dy = y - this.coords[3];
364
+ this.deltaX = dx;
365
+ this.deltaY = dy;
366
+ this.coords[2] = x;
367
+ this.coords[3] = y;
368
+ // Check if dx or dy are not 0 to check if the draggable has actually moved
369
+ // https://github.com/juliangarnier/anime/issues/1032
370
+ if (hasUpdated && (dx || dy)) {
371
+ this.onUpdate(this);
372
+ }
373
+ if (!hasReleased) {
374
+ this.updated = false;
375
+ } else {
376
+ this.computeVelocity(dx, dy);
377
+ this.angle = atan2(dy, dx);
378
+ }
379
+ };
380
+ this.animate.callbacks.onComplete = () => {
381
+ if ((!this.grabbed && this.released)) {
382
+ // Set released to false before calling onSettle to avoid recursion
383
+ this.released = false;
384
+ }
385
+ if (!this.manual) {
386
+ this.deltaX = 0;
387
+ this.deltaY = 0;
388
+ this.velocity = 0;
389
+ this.velocityStack[0] = 0;
390
+ this.velocityStack[1] = 0;
391
+ this.velocityStack[2] = 0;
392
+ this.velocityStackIndex = 0;
393
+ this.onSettle(this);
394
+ }
395
+ };
396
+ this.resizeTicker = new Timer({
397
+ autoplay: false,
398
+ duration: 150 * globals.timeScale,
399
+ onComplete: () => {
400
+ this.onResize(this);
401
+ this.refresh();
402
+ this.onAfterResize(this);
403
+ },
404
+ }).init();
405
+ this.parameters = parameters;
406
+ this.resizeObserver = new ResizeObserver(() => {
407
+ if (this.initialized) {
408
+ this.resizeTicker.restart();
409
+ } else {
410
+ this.initialized = true;
411
+ }
412
+ });
413
+ this.enable();
414
+ this.refresh();
415
+ this.resizeObserver.observe(this.$container);
416
+ if (!isObj(target)) this.resizeObserver.observe(this.$target);
417
+ }
418
+
419
+ /**
420
+ * @param {Number} dx
421
+ * @param {Number} dy
422
+ * @return {Number}
423
+ */
424
+ computeVelocity(dx, dy) {
425
+ const prevTime = this.velocityTime;
426
+ const curTime = now();
427
+ const elapsed = curTime - prevTime;
428
+ if (elapsed < 17) return this.velocity;
429
+ this.velocityTime = curTime;
430
+ const velocityStack = this.velocityStack;
431
+ const vMul = this.velocityMultiplier;
432
+ const minV = this.minVelocity;
433
+ const maxV = this.maxVelocity;
434
+ const vi = this.velocityStackIndex;
435
+ velocityStack[vi] = round(clamp((sqrt(dx * dx + dy * dy) / elapsed) * vMul, minV, maxV), 5);
436
+ const velocity = max(velocityStack[0], velocityStack[1], velocityStack[2]);
437
+ this.velocity = velocity;
438
+ this.velocityStackIndex = (vi + 1) % 3;
439
+ return velocity;
440
+ }
441
+
442
+ /**
443
+ * @param {Number} x
444
+ * @param {Boolean} [muteUpdateCallback]
445
+ * @return {this}
446
+ */
447
+ setX(x, muteUpdateCallback = false) {
448
+ if (this.disabled[0]) return;
449
+ const v = round(x, 5);
450
+ this.overshootTicker.pause();
451
+ this.manual = true;
452
+ this.updated = !muteUpdateCallback;
453
+ this.destX = v;
454
+ this.snapped[0] = snap(v, this.snapX);
455
+ this.animate[this.xProp](v, 0);
456
+ this.manual = false;
457
+ return this;
458
+ }
459
+
460
+ /**
461
+ * @param {Number} y
462
+ * @param {Boolean} [muteUpdateCallback]
463
+ * @return {this}
464
+ */
465
+ setY(y, muteUpdateCallback = false) {
466
+ if (this.disabled[1]) return;
467
+ const v = round(y, 5);
468
+ this.overshootTicker.pause();
469
+ this.manual = true;
470
+ this.updated = !muteUpdateCallback;
471
+ this.destY = v;
472
+ this.snapped[1] = snap(v, this.snapY);
473
+ this.animate[this.yProp](v, 0);
474
+ this.manual = false;
475
+ return this;
476
+ }
477
+
478
+ get x() {
479
+ return round(/** @type {Number} */(this.animate[this.xProp]()), globals.precision);
480
+ }
481
+
482
+ set x(x) {
483
+ this.setX(x, false);
484
+ }
485
+
486
+ get y() {
487
+ return round(/** @type {Number} */(this.animate[this.yProp]()), globals.precision);
488
+ }
489
+
490
+ set y(y) {
491
+ this.setY(y, false);
492
+ }
493
+
494
+ get progressX() {
495
+ return mapRange(this.x, this.containerBounds[3], this.containerBounds[1], 0, 1);
496
+ }
497
+
498
+ set progressX(x) {
499
+ this.setX(mapRange(x, 0, 1, this.containerBounds[3], this.containerBounds[1]), false);
500
+ }
501
+
502
+ get progressY() {
503
+ return mapRange(this.y, this.containerBounds[0], this.containerBounds[2], 0, 1);
504
+ }
505
+
506
+ set progressY(y) {
507
+ this.setY(mapRange(y, 0, 1, this.containerBounds[0], this.containerBounds[2]), false);
508
+ }
509
+
510
+ updateScrollCoords() {
511
+ const sx = round(this.useWin ? win.scrollX : this.$container.scrollLeft, 0);
512
+ const sy = round(this.useWin ? win.scrollY : this.$container.scrollTop, 0);
513
+ const [ cpt, cpr, cpb, cpl ] = this.containerPadding;
514
+ const threshold = this.scrollThreshold;
515
+ this.scroll.x = sx;
516
+ this.scroll.y = sy;
517
+ this.scrollBounds[0] = sy - this.targetBounds[0] + cpt - threshold;
518
+ this.scrollBounds[1] = sx - this.targetBounds[1] - cpr + threshold;
519
+ this.scrollBounds[2] = sy - this.targetBounds[2] - cpb + threshold;
520
+ this.scrollBounds[3] = sx - this.targetBounds[3] + cpl - threshold;
521
+ }
522
+
523
+ updateBoundingValues() {
524
+ const $container = this.$container;
525
+ // Return early if no $container defined to prevents error when reading scrollWidth / scrollHeight
526
+ // https://github.com/juliangarnier/anime/issues/1064
527
+ if (!$container) return;
528
+ const cx = this.x;
529
+ const cy = this.y;
530
+ const cx2 = this.coords[2];
531
+ const cy2 = this.coords[3];
532
+ // Prevents interfering with the scroll area in cases the target is outside of the container
533
+ // Make sure the temp coords are also adjuset to prevents wrong delta calculation on updates
534
+ this.coords[2] = 0;
535
+ this.coords[3] = 0;
536
+ this.setX(0, true);
537
+ this.setY(0, true);
538
+ this.transforms.remove();
539
+ const iw = this.window[0] = win.innerWidth;
540
+ const ih = this.window[1] = win.innerHeight;
541
+ const uw = this.useWin;
542
+ const sw = $container.scrollWidth;
543
+ const sh = $container.scrollHeight;
544
+ const fx = this.fixed;
545
+ const transformContainerRect = $container.getBoundingClientRect();
546
+ const [ cpt, cpr, cpb, cpl ] = this.containerPadding;
547
+ this.dragArea[0] = uw ? 0 : transformContainerRect.left;
548
+ this.dragArea[1] = uw ? 0 : transformContainerRect.top;
549
+ this.scrollView[0] = uw ? clamp(sw, iw, sw) : sw;
550
+ this.scrollView[1] = uw ? clamp(sh, ih, sh) : sh;
551
+ this.updateScrollCoords();
552
+ const { width, height, left, top, right, bottom } = $container.getBoundingClientRect();
553
+ this.dragArea[2] = round(uw ? clamp(width, iw, iw) : width, 0);
554
+ this.dragArea[3] = round(uw ? clamp(height, ih, ih) : height, 0);
555
+ const containerOverflow = get($container, 'overflow');
556
+ const visibleOverflow = containerOverflow === 'visible';
557
+ const hiddenOverflow = containerOverflow === 'hidden';
558
+ this.canScroll = fx ? false :
559
+ this.contained &&
560
+ (($container === doc.body && visibleOverflow) || (!hiddenOverflow && !visibleOverflow)) &&
561
+ (sw > this.dragArea[2] + cpl - cpr || sh > this.dragArea[3] + cpt - cpb) &&
562
+ (!this.containerArray || (this.containerArray && !isArr(this.containerArray)));
563
+ if (this.contained) {
564
+ const sx = this.scroll.x;
565
+ const sy = this.scroll.y;
566
+ const canScroll = this.canScroll;
567
+ const targetRect = this.$target.getBoundingClientRect();
568
+ const hiddenLeft = canScroll ? uw ? 0 : $container.scrollLeft : 0;
569
+ const hiddenTop = canScroll ? uw ? 0 : $container.scrollTop : 0;
570
+ const hiddenRight = canScroll ? this.scrollView[0] - hiddenLeft - width : 0;
571
+ const hiddenBottom = canScroll ? this.scrollView[1] - hiddenTop - height : 0;
572
+ this.targetBounds[0] = round((targetRect.top + sy) - (uw ? 0 : top), 0);
573
+ this.targetBounds[1] = round((targetRect.right + sx) - (uw ? iw : right), 0);
574
+ this.targetBounds[2] = round((targetRect.bottom + sy) - (uw ? ih : bottom), 0);
575
+ this.targetBounds[3] = round((targetRect.left + sx) - (uw ? 0 : left), 0);
576
+ if (this.containerArray) {
577
+ this.containerBounds[0] = this.containerArray[0] + cpt;
578
+ this.containerBounds[1] = this.containerArray[1] - cpr;
579
+ this.containerBounds[2] = this.containerArray[2] - cpb;
580
+ this.containerBounds[3] = this.containerArray[3] + cpl;
581
+ } else {
582
+ this.containerBounds[0] = -round(targetRect.top - (fx ? clamp(top, 0, ih) : top) + hiddenTop - cpt, 0);
583
+ this.containerBounds[1] = -round(targetRect.right - (fx ? clamp(right, 0, iw) : right) - hiddenRight + cpr, 0);
584
+ this.containerBounds[2] = -round(targetRect.bottom - (fx ? clamp(bottom, 0, ih) : bottom) - hiddenBottom + cpb, 0);
585
+ this.containerBounds[3] = -round(targetRect.left - (fx ? clamp(left, 0, iw) : left) + hiddenLeft - cpl, 0);
586
+ }
587
+ }
588
+ this.transforms.revert();
589
+ // Restore coordinates
590
+ this.coords[2] = cx2;
591
+ this.coords[3] = cy2;
592
+ this.setX(cx, true);
593
+ this.setY(cy, true);
594
+ }
595
+
596
+ /**
597
+ * @param {Array} bounds
598
+ * @param {Number} x
599
+ * @param {Number} y
600
+ * @return {Number}
601
+ */
602
+ isOutOfBounds(bounds, x, y) {
603
+ // Returns 0 if not OB, 1 if x is OB, 2 if y is OB, 3 if both x and y are OB
604
+ if (!this.contained) return 0;
605
+ const [ bt, br, bb, bl ] = bounds;
606
+ const [ dx, dy ] = this.disabled;
607
+ const obx = !dx && x < bl || !dx && x > br;
608
+ const oby = !dy && y < bt || !dy && y > bb;
609
+ return obx && !oby ? 1 : !obx && oby ? 2 : obx && oby ? 3 : 0;
610
+ }
611
+
612
+ refresh() {
613
+ const params = this.parameters;
614
+ const paramX = params.x;
615
+ const paramY = params.y;
616
+ const container = parseDraggableFunctionParameter(params.container, this);
617
+ const cp = parseDraggableFunctionParameter(params.containerPadding, this) || 0;
618
+ const containerPadding = /** @type {[Number, Number, Number, Number]} */(isArr(cp) ? cp : [cp, cp, cp, cp]);
619
+ const cx = this.x;
620
+ const cy = this.y;
621
+ const parsedCursorStyles = parseDraggableFunctionParameter(params.cursor, this);
622
+ const cursorStyles = { onHover: 'grab', onGrab: 'grabbing' };
623
+ if (parsedCursorStyles) {
624
+ const { onHover, onGrab } = /** @type {DraggableCursorParams} */(parsedCursorStyles);
625
+ if (onHover) cursorStyles.onHover = onHover;
626
+ if (onGrab) cursorStyles.onGrab = onGrab;
627
+ }
628
+ this.containerArray = isArr(container) ? container : null;
629
+ this.$container = /** @type {HTMLElement} */(container && !this.containerArray ? parseTargets(/** @type {DOMTarget} */(container))[0] : doc.body);
630
+ this.useWin = this.$container === doc.body;
631
+ /** @type {Window | HTMLElement} */
632
+ this.$scrollContainer = this.useWin ? win : this.$container;
633
+ this.isFinePointer = matchMedia('(pointer:fine)').matches;
634
+ this.containerPadding = setValue(containerPadding, [0, 0, 0, 0]);
635
+ this.containerFriction = clamp(setValue(parseDraggableFunctionParameter(params.containerFriction, this), .8), 0, 1);
636
+ this.releaseContainerFriction = clamp(setValue(parseDraggableFunctionParameter(params.releaseContainerFriction, this), this.containerFriction), 0, 1);
637
+ this.snapX = parseDraggableFunctionParameter(isObj(paramX) && !isUnd(paramX.snap) ? paramX.snap : params.snap, this);
638
+ this.snapY = parseDraggableFunctionParameter(isObj(paramY) && !isUnd(paramY.snap) ? paramY.snap : params.snap, this);
639
+ this.scrollSpeed = setValue(parseDraggableFunctionParameter(params.scrollSpeed, this), 1.5);
640
+ this.scrollThreshold = setValue(parseDraggableFunctionParameter(params.scrollThreshold, this), 20);
641
+ this.dragSpeed = setValue(parseDraggableFunctionParameter(params.dragSpeed, this), 1);
642
+ this.minVelocity = setValue(parseDraggableFunctionParameter(params.minVelocity, this), 0);
643
+ this.maxVelocity = setValue(parseDraggableFunctionParameter(params.maxVelocity, this), 50);
644
+ this.velocityMultiplier = setValue(parseDraggableFunctionParameter(params.velocityMultiplier, this), 1);
645
+ this.cursor = parsedCursorStyles === false ? false : cursorStyles;
646
+ this.updateBoundingValues();
647
+
648
+ // const ob = this.isOutOfBounds(this.containerBounds, this.x, this.y);
649
+ // if (ob === 1 || ob === 3) this.progressX = px;
650
+ // if (ob === 2 || ob === 3) this.progressY = py;
651
+
652
+ // if (this.initialized && this.contained) {
653
+ // if (this.progressX !== px) this.progressX = px;
654
+ // if (this.progressY !== py) this.progressY = py;
655
+ // }
656
+
657
+ const [ bt, br, bb, bl ] = this.containerBounds;
658
+ this.setX(clamp(cx, bl, br), true);
659
+ this.setY(clamp(cy, bt, bb), true);
660
+ }
661
+
662
+ update() {
663
+ this.updateScrollCoords();
664
+ if (this.canScroll) {
665
+ const [ cpt, cpr, cpb, cpl ] = this.containerPadding;
666
+ const [ sw, sh ] = this.scrollView;
667
+ const daw = this.dragArea[2];
668
+ const dah = this.dragArea[3];
669
+ const csx = this.scroll.x;
670
+ const csy = this.scroll.y;
671
+ const nsw = this.$container.scrollWidth;
672
+ const nsh = this.$container.scrollHeight;
673
+ const csw = this.useWin ? clamp(nsw, this.window[0], nsw) : nsw;
674
+ const csh = this.useWin ? clamp(nsh, this.window[1], nsh) : nsh;
675
+ const swd = sw - csw;
676
+ const shd = sh - csh;
677
+ // Handle cases where the scrollarea dimensions changes during drag
678
+ if (this.dragged && swd > 0) {
679
+ this.coords[0] -= swd;
680
+ this.scrollView[0] = csw;
681
+ }
682
+ if (this.dragged && shd > 0) {
683
+ this.coords[1] -= shd;
684
+ this.scrollView[1] = csh;
685
+ }
686
+ // Handle autoscroll when target is at the edges of the scroll bounds
687
+ const s = this.scrollSpeed * 10;
688
+ const threshold = this.scrollThreshold;
689
+ const [ x, y ] = this.coords;
690
+ const [ st, sr, sb, sl ] = this.scrollBounds;
691
+ const t = round(clamp((y - st + cpt) / threshold, -1, 0) * s, 0);
692
+ const r = round(clamp((x - sr - cpr) / threshold, 0, 1) * s, 0);
693
+ const b = round(clamp((y - sb - cpb) / threshold, 0, 1) * s, 0);
694
+ const l = round(clamp((x - sl + cpl) / threshold, -1, 0) * s, 0);
695
+ if (t || b || l || r) {
696
+ const [nx, ny] = this.disabled;
697
+ let scrollX = csx;
698
+ let scrollY = csy;
699
+ if (!nx) {
700
+ scrollX = round(clamp(csx + (l || r), 0, sw - daw), 0);
701
+ this.coords[0] -= csx - scrollX;
702
+ }
703
+ if (!ny) {
704
+ scrollY = round(clamp(csy + (t || b), 0, sh - dah), 0);
705
+ this.coords[1] -= csy - scrollY;
706
+ }
707
+ // Note: Safari mobile requires to use different scroll methods depending if using the window or not
708
+ if (this.useWin) {
709
+ this.$scrollContainer.scrollBy(-(csx - scrollX), -(csy - scrollY));
710
+ } else {
711
+ this.$scrollContainer.scrollTo(scrollX, scrollY);
712
+ }
713
+ }
714
+ }
715
+ const [ ct, cr, cb, cl ] = this.containerBounds;
716
+ const [ px1, py1, px2, py2, px3, py3 ] = this.pointer;
717
+ this.coords[0] += (px1 - px3) * this.dragSpeed;
718
+ this.coords[1] += (py1 - py3) * this.dragSpeed;
719
+ this.pointer[4] = px1;
720
+ this.pointer[5] = py1;
721
+ const [ cx, cy ] = this.coords;
722
+ const [ sx, sy ] = this.snapped;
723
+ const cf = (1 - this.containerFriction) * this.dragSpeed;
724
+ this.setX(cx > cr ? cr + (cx - cr) * cf : cx < cl ? cl + (cx - cl) * cf : cx, false);
725
+ this.setY(cy > cb ? cb + (cy - cb) * cf : cy < ct ? ct + (cy - ct) * cf : cy, false);
726
+ this.computeVelocity(px1 - px3, py1 - py3);
727
+ this.angle = atan2(py1 - py2, px1 - px2);
728
+ const [ nsx, nsy ] = this.snapped;
729
+ if (nsx !== sx && this.snapX || nsy !== sy && this.snapY) {
730
+ this.onSnap(this);
731
+ }
732
+ }
733
+
734
+ stop() {
735
+ this.updateTicker.pause();
736
+ this.overshootTicker.pause();
737
+ // Pauses the in bounds onRelease animations
738
+ for (let prop in this.animate.animations) this.animate.animations[prop].pause();
739
+ removeTargetsFromRenderable([this], null, 'x');
740
+ removeTargetsFromRenderable([this], null, 'y');
741
+ removeTargetsFromRenderable([this], null, 'progressX');
742
+ removeTargetsFromRenderable([this], null, 'progressY');
743
+ removeTargetsFromRenderable([this.scroll]); // Removes any active animations on the container scroll
744
+ removeTargetsFromRenderable([this.overshootCoords]); // Removes active overshoot animations
745
+ return this;
746
+ }
747
+
748
+ /**
749
+ * @param {Number} [duration]
750
+ * @param {Number} [gap]
751
+ * @param {EasingParam} [ease]
752
+ * @return {this}
753
+ */
754
+ scrollInView(duration, gap = 0, ease = eases.inOutQuad) {
755
+ this.updateScrollCoords();
756
+ const x = this.destX;
757
+ const y = this.destY;
758
+ const scroll = this.scroll;
759
+ const scrollBounds = this.scrollBounds;
760
+ const canScroll = this.canScroll;
761
+ if (!this.containerArray && this.isOutOfBounds(scrollBounds, x, y)) {
762
+ const [ st, sr, sb, sl ] = scrollBounds;
763
+ const t = round(clamp(y - st, -maxValue, 0), 0);
764
+ const r = round(clamp(x - sr, 0, maxValue), 0);
765
+ const b = round(clamp(y - sb, 0, maxValue), 0);
766
+ const l = round(clamp(x - sl, -maxValue, 0), 0);
767
+ new JSAnimation(scroll, {
768
+ x: round(scroll.x + (l ? l - gap : r ? r + gap : 0), 0),
769
+ y: round(scroll.y + (t ? t - gap : b ? b + gap : 0), 0),
770
+ duration: isUnd(duration) ? 350 * globals.timeScale : duration,
771
+ ease,
772
+ onUpdate: () => {
773
+ this.canScroll = false;
774
+ this.$scrollContainer.scrollTo(scroll.x, scroll.y);
775
+ }
776
+ }).init().then(() => {
777
+ this.canScroll = canScroll;
778
+ });
779
+ }
780
+ return this;
781
+ }
782
+
783
+ handleHover() {
784
+ if (this.isFinePointer && this.cursor && !this.cursorStyles) {
785
+ this.cursorStyles = set(this.$trigger, {
786
+ cursor: /** @type {DraggableCursorParams} */(this.cursor).onHover
787
+ });
788
+ }
789
+ }
790
+
791
+ /**
792
+ * @param {Number} [duration]
793
+ * @param {Number} [gap]
794
+ * @param {EasingParam} [ease]
795
+ * @return {this}
796
+ */
797
+ animateInView(duration, gap = 0, ease = eases.inOutQuad) {
798
+ this.stop();
799
+ this.updateBoundingValues();
800
+ const x = this.x;
801
+ const y = this.y;
802
+ const [ cpt, cpr, cpb, cpl ] = this.containerPadding;
803
+ const bt = this.scroll.y - this.targetBounds[0] + cpt + gap;
804
+ const br = this.scroll.x - this.targetBounds[1] - cpr - gap;
805
+ const bb = this.scroll.y - this.targetBounds[2] - cpb - gap;
806
+ const bl = this.scroll.x - this.targetBounds[3] + cpl + gap;
807
+ const ob = this.isOutOfBounds([bt, br, bb, bl], x, y);
808
+ if (ob) {
809
+ const [ disabledX, disabledY ] = this.disabled;
810
+ const destX = clamp(snap(x, this.snapX), bl, br);
811
+ const destY = clamp(snap(y, this.snapY), bt, bb);
812
+ const dur = isUnd(duration) ? 350 * globals.timeScale : duration;
813
+ if (!disabledX && (ob === 1 || ob === 3)) this.animate[this.xProp](destX, dur, ease);
814
+ if (!disabledY && (ob === 2 || ob === 3)) this.animate[this.yProp](destY, dur, ease);
815
+ }
816
+ return this;
817
+ }
818
+
819
+ /**
820
+ * @param {MouseEvent|TouchEvent} e
821
+ */
822
+ handleDown(e) {
823
+ const $eTarget = /** @type {HTMLElement} */(e.target);
824
+ if (this.grabbed || /** @type {HTMLInputElement} */($eTarget).type === 'range') return;
825
+
826
+ e.stopPropagation();
827
+
828
+ this.grabbed = true;
829
+ this.released = false;
830
+ this.stop();
831
+ this.updateBoundingValues();
832
+ const touches = /** @type {TouchEvent} */(e).changedTouches;
833
+ const eventX = touches ? touches[0].clientX : /** @type {MouseEvent} */(e).clientX;
834
+ const eventY = touches ? touches[0].clientY : /** @type {MouseEvent} */(e).clientY;
835
+ const { x, y } = this.transforms.normalizePoint(eventX, eventY);
836
+ const [ ct, cr, cb, cl ] = this.containerBounds;
837
+ const cf = (1 - this.containerFriction) * this.dragSpeed;
838
+ const cx = this.x;
839
+ const cy = this.y;
840
+ this.coords[0] = this.coords[2] = !cf ? cx : cx > cr ? cr + (cx - cr) / cf : cx < cl ? cl + (cx - cl) / cf : cx;
841
+ this.coords[1] = this.coords[3] = !cf ? cy : cy > cb ? cb + (cy - cb) / cf : cy < ct ? ct + (cy - ct) / cf : cy;
842
+ this.pointer[0] = x;
843
+ this.pointer[1] = y;
844
+ this.pointer[2] = x;
845
+ this.pointer[3] = y;
846
+ this.pointer[4] = x;
847
+ this.pointer[5] = y;
848
+ this.pointer[6] = x;
849
+ this.pointer[7] = y;
850
+ this.deltaX = 0;
851
+ this.deltaY = 0;
852
+ this.velocity = 0;
853
+ this.velocityStack[0] = 0;
854
+ this.velocityStack[1] = 0;
855
+ this.velocityStack[2] = 0;
856
+ this.velocityStackIndex = 0;
857
+ this.angle = 0;
858
+ if (this.targetStyles) {
859
+ this.targetStyles.revert();
860
+ this.targetStyles = null;
861
+ }
862
+ const z = /** @type {Number} */(get(this.$target, 'zIndex', false));
863
+ zIndex = (z > zIndex ? z : zIndex) + 1;
864
+ this.targetStyles = set(this.$target, { zIndex });
865
+ if (this.triggerStyles) {
866
+ this.triggerStyles.revert();
867
+ this.triggerStyles = null;
868
+ }
869
+ if (this.cursorStyles) {
870
+ this.cursorStyles.revert();
871
+ this.cursorStyles = null;
872
+ }
873
+ if (this.isFinePointer && this.cursor) {
874
+ this.bodyStyles = set(doc.body, {
875
+ cursor: /** @type {DraggableCursorParams} */(this.cursor).onGrab
876
+ });
877
+ }
878
+ this.scrollInView(100, 0, eases.out(3));
879
+ this.onGrab(this);
880
+
881
+ doc.addEventListener('touchmove', this);
882
+ doc.addEventListener('touchend', this);
883
+ doc.addEventListener('touchcancel', this);
884
+ doc.addEventListener('mousemove', this);
885
+ doc.addEventListener('mouseup', this);
886
+ doc.addEventListener('selectstart', this);
887
+ }
888
+
889
+ /**
890
+ * @param {MouseEvent|TouchEvent} e
891
+ */
892
+ handleMove(e) {
893
+ if (!this.grabbed) return;
894
+ const touches = /** @type {TouchEvent} */(e).changedTouches;
895
+ const eventX = touches ? touches[0].clientX : /** @type {MouseEvent} */(e).clientX;
896
+ const eventY = touches ? touches[0].clientY : /** @type {MouseEvent} */(e).clientY;
897
+ const { x, y } = this.transforms.normalizePoint(eventX, eventY);
898
+ const movedX = x - this.pointer[6];
899
+ const movedY = y - this.pointer[7];
900
+
901
+ let $parent = /** @type {HTMLElement} */(e.target);
902
+ let isAtTop = false;
903
+ let isAtBottom = false;
904
+ let canTouchScroll = false;
905
+
906
+ while (touches && $parent && $parent !== this.$trigger) {
907
+ const overflowY = get($parent, 'overflow-y');
908
+ if (overflowY !== 'hidden' && overflowY !== 'visible') {
909
+ const { scrollTop, scrollHeight, clientHeight } = $parent;
910
+ if (scrollHeight > clientHeight) {
911
+ canTouchScroll = true;
912
+ isAtTop = scrollTop <= 3;
913
+ isAtBottom = scrollTop >= (scrollHeight - clientHeight) - 3;
914
+ break;
915
+ }
916
+ }
917
+ $parent = $parent.parentElement;
918
+ }
919
+
920
+ if (canTouchScroll && ((!isAtTop && !isAtBottom) || (isAtTop && movedY < 0) || (isAtBottom && movedY > 0))) {
921
+
922
+ this.pointer[0] = x;
923
+ this.pointer[1] = y;
924
+ this.pointer[2] = x;
925
+ this.pointer[3] = y;
926
+ this.pointer[4] = x;
927
+ this.pointer[5] = y;
928
+ this.pointer[6] = x;
929
+ this.pointer[7] = y;
930
+
931
+ } else {
932
+
933
+ preventDefault(e);
934
+
935
+ // Needed to prevents click on handleUp
936
+ if (!this.triggerStyles) this.triggerStyles = set(this.$trigger, { pointerEvents: 'none' });
937
+ // Needed to prevent page scroll while dragging on touch devvice
938
+ this.$trigger.addEventListener('touchstart', preventDefault, { passive: false });
939
+ this.$trigger.addEventListener('touchmove', preventDefault, { passive: false });
940
+ this.$trigger.addEventListener('touchend', preventDefault);
941
+
942
+
943
+ if ((!this.disabled[0] && abs(movedX) > 3) || (!this.disabled[1] && abs(movedY) > 3)) {
944
+
945
+ this.updateTicker.resume();
946
+ this.pointer[2] = this.pointer[0];
947
+ this.pointer[3] = this.pointer[1];
948
+ this.pointer[0] = x;
949
+ this.pointer[1] = y;
950
+ this.dragged = true;
951
+ this.released = false;
952
+ this.onDrag(this);
953
+ }
954
+ }
955
+ }
956
+
957
+ handleUp() {
958
+
959
+ if (!this.grabbed) return;
960
+
961
+ this.updateTicker.pause();
962
+
963
+ if (this.triggerStyles) {
964
+ this.triggerStyles.revert();
965
+ this.triggerStyles = null;
966
+ }
967
+
968
+ if (this.bodyStyles) {
969
+ this.bodyStyles.revert();
970
+ this.bodyStyles = null;
971
+ }
972
+
973
+ const [ disabledX, disabledY ] = this.disabled;
974
+ const [ px1, py1, px2, py2, px3, py3 ] = this.pointer;
975
+ const [ ct, cr, cb, cl ] = this.containerBounds;
976
+ const [ sx, sy ] = this.snapped;
977
+ const springX = this.releaseXSpring;
978
+ const springY = this.releaseYSpring;
979
+ const releaseEase = this.releaseEase;
980
+ const hasReleaseSpring = this.hasReleaseSpring;
981
+ const overshootCoords = this.overshootCoords;
982
+ const cx = this.x;
983
+ const cy = this.y;
984
+ const pv = this.computeVelocity(px1 - px3, py1 - py3);
985
+ const pa = this.angle = atan2(py1 - py2, px1 - px2);
986
+ const ds = pv * 150;
987
+ const cf = (1 - this.releaseContainerFriction) * this.dragSpeed;
988
+ const nx = cx + (cos(pa) * ds);
989
+ const ny = cy + (sin(pa) * ds);
990
+ const bx = nx > cr ? cr + (nx - cr) * cf : nx < cl ? cl + (nx - cl) * cf : nx;
991
+ const by = ny > cb ? cb + (ny - cb) * cf : ny < ct ? ct + (ny - ct) * cf : ny;
992
+ const dx = this.destX = clamp(round(snap(bx, this.snapX), 5), cl, cr);
993
+ const dy = this.destY = clamp(round(snap(by, this.snapY), 5), ct, cb);
994
+ const ob = this.isOutOfBounds(this.containerBounds, nx, ny);
995
+
996
+ let durationX = 0;
997
+ let durationY = 0;
998
+ let easeX = releaseEase;
999
+ let easeY = releaseEase;
1000
+ let longestReleaseDuration = 0;
1001
+
1002
+ overshootCoords.x = cx;
1003
+ overshootCoords.y = cy;
1004
+
1005
+ if (!disabledX) {
1006
+ const directionX = dx === cr ? cx > cr ? -1 : 1 : cx < cl ? -1 : 1;
1007
+ const distanceX = round(cx - dx, 0);
1008
+ springX.velocity = disabledY && hasReleaseSpring ? distanceX ? (ds * directionX) / abs(distanceX) : 0 : pv;
1009
+ const { ease, duration, restDuration } = springX;
1010
+ durationX = cx === dx ? 0 : hasReleaseSpring ? duration : duration - (restDuration * globals.timeScale);
1011
+ if (hasReleaseSpring) easeX = ease;
1012
+ if (durationX > longestReleaseDuration) longestReleaseDuration = durationX;
1013
+ }
1014
+
1015
+ if (!disabledY) {
1016
+ const directionY = dy === cb ? cy > cb ? -1 : 1 : cy < ct ? -1 : 1;
1017
+ const distanceY = round(cy - dy, 0);
1018
+ springY.velocity = disabledX && hasReleaseSpring ? distanceY ? (ds * directionY) / abs(distanceY) : 0 : pv;
1019
+ const { ease, duration, restDuration } = springY;
1020
+ durationY = cy === dy ? 0 : hasReleaseSpring ? duration : duration - (restDuration * globals.timeScale);
1021
+ if (hasReleaseSpring) easeY = ease;
1022
+ if (durationY > longestReleaseDuration) longestReleaseDuration = durationY;
1023
+ }
1024
+
1025
+ if (!hasReleaseSpring && ob && cf && (durationX || durationY)) {
1026
+
1027
+ const composition = compositionTypes.blend;
1028
+
1029
+ new JSAnimation(overshootCoords, {
1030
+ x: { to: bx, duration: durationX * .65 },
1031
+ y: { to: by, duration: durationY * .65 },
1032
+ ease: releaseEase,
1033
+ composition,
1034
+ }).init();
1035
+
1036
+ new JSAnimation(overshootCoords, {
1037
+ x: { to: dx, duration: durationX },
1038
+ y: { to: dy, duration: durationY },
1039
+ ease: releaseEase,
1040
+ composition,
1041
+ }).init();
1042
+
1043
+ this.overshootTicker.stretch(max(durationX, durationY)).restart();
1044
+
1045
+ } else {
1046
+
1047
+ if (!disabledX) this.animate[this.xProp](dx, durationX, easeX);
1048
+ if (!disabledY) this.animate[this.yProp](dy, durationY, easeY);
1049
+
1050
+ }
1051
+
1052
+ this.scrollInView(longestReleaseDuration, this.scrollThreshold, releaseEase);
1053
+
1054
+ let hasSnapped = false;
1055
+
1056
+ if (dx !== sx) {
1057
+ this.snapped[0] = dx;
1058
+ if (this.snapX) hasSnapped = true;
1059
+ }
1060
+
1061
+ if (dy !== sy && this.snapY) {
1062
+ this.snapped[1] = dy;
1063
+ if (this.snapY) hasSnapped = true;
1064
+ }
1065
+
1066
+ if (hasSnapped) this.onSnap(this);
1067
+
1068
+ this.grabbed = false;
1069
+ this.dragged = false;
1070
+ this.updated = true;
1071
+ this.released = true;
1072
+
1073
+ // It's important to trigger the callback after the release animations to be able to cancel them
1074
+ this.onRelease(this);
1075
+
1076
+ this.$trigger.removeEventListener('touchstart', preventDefault);
1077
+ this.$trigger.removeEventListener('touchmove', preventDefault);
1078
+ this.$trigger.removeEventListener('touchend', preventDefault);
1079
+
1080
+ doc.removeEventListener('touchmove', this);
1081
+ doc.removeEventListener('touchend', this);
1082
+ doc.removeEventListener('touchcancel', this);
1083
+ doc.removeEventListener('mousemove', this);
1084
+ doc.removeEventListener('mouseup', this);
1085
+ doc.removeEventListener('selectstart', this);
1086
+ }
1087
+
1088
+ reset() {
1089
+ this.stop();
1090
+ this.resizeTicker.pause();
1091
+ this.grabbed = false;
1092
+ this.dragged = false;
1093
+ this.updated = false;
1094
+ this.released = false;
1095
+ this.canScroll = false;
1096
+ this.setX(0, true);
1097
+ this.setY(0, true);
1098
+ this.coords[0] = 0;
1099
+ this.coords[1] = 0;
1100
+ this.pointer[0] = 0;
1101
+ this.pointer[1] = 0;
1102
+ this.pointer[2] = 0;
1103
+ this.pointer[3] = 0;
1104
+ this.pointer[4] = 0;
1105
+ this.pointer[5] = 0;
1106
+ this.pointer[6] = 0;
1107
+ this.pointer[7] = 0;
1108
+ this.velocity = 0;
1109
+ this.velocityStack[0] = 0;
1110
+ this.velocityStack[1] = 0;
1111
+ this.velocityStack[2] = 0;
1112
+ this.velocityStackIndex = 0;
1113
+ this.angle = 0;
1114
+ return this;
1115
+ }
1116
+
1117
+ enable() {
1118
+ if (!this.enabled) {
1119
+ this.enabled = true;
1120
+ this.$target.classList.remove('is-disabled');
1121
+ this.touchActionStyles = set(this.$trigger, {
1122
+ touchAction: this.disabled[0] ? 'pan-x' : this.disabled[1] ? 'pan-y' : 'none'
1123
+ });
1124
+ this.$trigger.addEventListener('touchstart', this, { passive: true });
1125
+ this.$trigger.addEventListener('mousedown', this, { passive: true });
1126
+ this.$trigger.addEventListener('mouseenter', this);
1127
+ }
1128
+ return this;
1129
+ }
1130
+
1131
+ disable() {
1132
+ this.enabled = false;
1133
+ this.grabbed = false;
1134
+ this.dragged = false;
1135
+ this.updated = false;
1136
+ this.released = false;
1137
+ this.canScroll = false;
1138
+ this.touchActionStyles.revert();
1139
+ if (this.cursorStyles) {
1140
+ this.cursorStyles.revert();
1141
+ this.cursorStyles = null;
1142
+ }
1143
+ if (this.triggerStyles) {
1144
+ this.triggerStyles.revert();
1145
+ this.triggerStyles = null;
1146
+ }
1147
+ if (this.bodyStyles) {
1148
+ this.bodyStyles.revert();
1149
+ this.bodyStyles = null;
1150
+ }
1151
+ if (this.targetStyles) {
1152
+ this.targetStyles.revert();
1153
+ this.targetStyles = null;
1154
+ }
1155
+ this.$target.classList.add('is-disabled');
1156
+ this.$trigger.removeEventListener('touchstart', this);
1157
+ this.$trigger.removeEventListener('mousedown', this);
1158
+ this.$trigger.removeEventListener('mouseenter', this);
1159
+ doc.removeEventListener('touchmove', this);
1160
+ doc.removeEventListener('touchend', this);
1161
+ doc.removeEventListener('touchcancel', this);
1162
+ doc.removeEventListener('mousemove', this);
1163
+ doc.removeEventListener('mouseup', this);
1164
+ doc.removeEventListener('selectstart', this);
1165
+ return this;
1166
+ }
1167
+
1168
+ revert() {
1169
+ this.reset();
1170
+ this.disable();
1171
+ this.$target.classList.remove('is-disabled');
1172
+ this.updateTicker.revert();
1173
+ this.overshootTicker.revert();
1174
+ this.resizeTicker.revert();
1175
+ this.animate.revert();
1176
+ this.resizeObserver.disconnect();
1177
+ return this;
1178
+ }
1179
+
1180
+ /**
1181
+ * @param {Event} e
1182
+ */
1183
+ handleEvent(e) {
1184
+ switch (e.type) {
1185
+ case 'mousedown':
1186
+ this.handleDown(/** @type {MouseEvent} */(e));
1187
+ break;
1188
+ case 'touchstart':
1189
+ this.handleDown(/** @type {TouchEvent} */(e));
1190
+ break;
1191
+ case 'mousemove':
1192
+ this.handleMove(/** @type {MouseEvent} */(e));
1193
+ break;
1194
+ case 'touchmove':
1195
+ this.handleMove(/** @type {TouchEvent} */(e));
1196
+ break;
1197
+ case 'mouseup':
1198
+ this.handleUp();
1199
+ break;
1200
+ case 'touchend':
1201
+ this.handleUp();
1202
+ break;
1203
+ case 'touchcancel':
1204
+ this.handleUp();
1205
+ break;
1206
+ case 'mouseenter':
1207
+ this.handleHover();
1208
+ break;
1209
+ case 'selectstart':
1210
+ preventDefault(e);
1211
+ break;
1212
+ }
1213
+ }
1214
+ }
1215
+
1216
+ /**
1217
+ * @param {TargetsParam} target
1218
+ * @param {DraggableParams} [parameters]
1219
+ * @return {Draggable}
1220
+ */
1221
+ const createDraggable = (target, parameters) => new Draggable(target, parameters);
1222
+
1223
+ export { Draggable, createDraggable };