select-animation 1.6.0 → 1.6.1

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 (2) hide show
  1. package/package.json +1 -1
  2. package/select-animation.js +821 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "select-animation",
3
- "version": "1.6.0",
3
+ "version": "1.6.1",
4
4
  "description": "High-performance JavaScript animation engine for organic & fluid motion",
5
5
  "main": "select-animation.js",
6
6
  "scripts": {
@@ -1,4 +1,101 @@
1
- // -----------------------------
1
+ /* -------------------------------------------------------------------------
2
+ * Select-Animation: A High-Performance JavaScript Animation Engine
3
+ * Designed for fluid motion and organic UI transitions.
4
+ * Version: v1
5
+ * Author: Housseyn Cheriet
6
+ * Copyright: ©2026 Housseyn Cheriet
7
+ * License: MIT
8
+ * ------------------------------------------------------------------------- */
9
+
10
+
11
+ (function (global) {
12
+ "use strict";
13
+
14
+ // -----------------------------
15
+ // requestAnimationFrame polyfill
16
+ // Ensures consistent animation frame behavior across older browsers.
17
+ // -----------------------------
18
+ let _lastTime = 0;
19
+ const _vendors = ["ms", "moz", "webkit", "o"];
20
+ for (let i = 0; i < _vendors.length && !global.requestAnimationFrame; ++i) {
21
+ global.requestAnimationFrame = global[_vendors[i] + "RequestAnimationFrame"];
22
+ global.cancelAnimationFrame = global[_vendors[i] + "CancelAnimationFrame"] || global[_vendors[i] + "CancelRequestAnimationFrame"];
23
+ }
24
+
25
+ if (!global.requestAnimationFrame) {
26
+ global.requestAnimationFrame = function (callback) {
27
+ const currTime = new Date().getTime();
28
+ const timeToCall = Math.max(0, 16 - (currTime - _lastTime));
29
+ const id = global.setTimeout(function () {
30
+ callback(currTime + timeToCall);
31
+ }, timeToCall);
32
+ _lastTime = currTime + timeToCall;
33
+ return id;
34
+ };
35
+ }
36
+
37
+ if (!global.cancelAnimationFrame) {
38
+ global.cancelAnimationFrame = function (id) {
39
+ clearTimeout(id);
40
+ };
41
+ }
42
+
43
+ // -----------------------------
44
+ // Internal defaults and mappings
45
+ // Color defaults and map from logical property -> CSS format.
46
+ // -----------------------------
47
+ const COLOR_DEFAULTS = { rgbR: 255, rgbG: 255, rgbB: 255, rgbA: 1 };
48
+
49
+ const COLOR_PROPERTIES = {
50
+ color: COLOR_DEFAULTS,
51
+ background: COLOR_DEFAULTS,
52
+ backgroundColor: COLOR_DEFAULTS,
53
+ borderColor: COLOR_DEFAULTS
54
+ };
55
+
56
+ const PROPERTY_FORMAT_MAP = {
57
+ zIndex: "*",
58
+ left: "*px",
59
+ top: "*px",
60
+ bottom: "*px",
61
+ right: "*px",
62
+ width: "*px",
63
+ height: "*px",
64
+ minWidth: "*px",
65
+ minHeight: "*px",
66
+ maxWidth: "*px",
67
+ maxHeight: "*px",
68
+ padding: "*px",
69
+ margin: "*px",
70
+ borderRadius: "*%",
71
+ borderWidth: "*px",
72
+ borderTopWidth: "*px",
73
+ borderRightWidth: "*px",
74
+ borderBottomWidth: "*px",
75
+ borderLeftWidth: "*px",
76
+ borderImageWidth: "*px",
77
+ strokeWidth: "*px",
78
+ strokeHeight: "*px",
79
+ strokeOpacity: "*",
80
+ opacity: "*",
81
+ translateX: "translateX(*px)",
82
+ translateY: "translateY(*px)",
83
+ translateZ: "translateZ(*px)",
84
+ rotateX: "rotateX(*deg)",
85
+ rotateY: "rotateY(*deg)",
86
+ rotateZ: "rotateZ(*deg)",
87
+ scale: "scale(*)",
88
+ scaleX: "scaleX(*)",
89
+ scaleY: "scaleY(*)",
90
+ skewX: "skewX(*deg)",
91
+ skewY: "skewY(*deg)",
92
+ rgbR: "rgba(*,",
93
+ rgbG: "*,",
94
+ rgbB: "*,",
95
+ rgba: "rgba(rgbR,rgbG,rgbB,rgbA)"
96
+ };
97
+
98
+ // -----------------------------
2
99
  // select: simple DOM selector utility
3
100
  // Returns flat array of matched elements given one or more selectors
4
101
  // Usage: select('.class', '#id')
@@ -43,4 +140,726 @@
43
140
  });
44
141
 
45
142
  return allElements;
46
- };
143
+ };
144
+
145
+ // -----------------------------
146
+ // animate: animation factory
147
+ // Accepts animation definitions and returns a runner function to start animations on targets.
148
+ // -----------------------------
149
+ const animate = function () {
150
+ const definitions = arguments;
151
+ const defsCopy = copyObj(definitions);
152
+
153
+ return function () {
154
+ let tmp, i, propIndex, fromItem, toItem, valFrom, valTo, t;
155
+ let grouped = [];
156
+ let expectNextGroup = false;
157
+ let staging = { color: {}, transform: {}, from: {}, to: {} };
158
+
159
+ // Process the definitions to map elements to their animation settings
160
+ buildPlan();
161
+
162
+ function buildPlan() {
163
+ let secondPass = false;
164
+
165
+ for (let c = 0, total = definitions.length; c < total; c++) {
166
+ propIndex = 0;
167
+ // If current item is an element or an array of elements
168
+ if (expectNextGroup || Array.isArray(defsCopy[c]) || isElement(defsCopy[c])) {
169
+ if (secondPass) {
170
+ Array.isArray(defsCopy[c]) || (defsCopy[c] = [defsCopy[c]]);
171
+ Array.prototype.push.apply(grouped, defsCopy[c]);
172
+ }
173
+ expectNextGroup = false;
174
+ }
175
+ // --- Handle Configuration Object with Validation ---
176
+ else if (typeof defsCopy[c] === 'object' && defsCopy[c] !== null) {
177
+ if (secondPass) {
178
+ // Execute the animation runner for the current group
179
+ runner(grouped, definitions, defsCopy, c)();
180
+ } else {
181
+ expectNextGroup = false;
182
+
183
+ // 1. Validate Duration and Animation Type
184
+ defsCopy[c].duration = (typeof defsCopy[c].duration === 'number' && defsCopy[c].duration > 0) ? defsCopy[c].duration : 1000;
185
+
186
+ let requestedType = defsCopy[c].typeAnimation;
187
+
188
+ if (requestedType === "vibration" && defsCopy[c].vibrationStep === undefined) {
189
+ defsCopy[c].vibrationStep = 6;
190
+ } else if (requestedType) {
191
+ t = getNumber(requestedType);
192
+ if (t && t.length === 4) {
193
+ defsCopy[c].cubicbezier = t;
194
+ defsCopy[c].typeAnimation = "cubicbezier";
195
+ } else {
196
+ // STOP EXECUTION: If easing is not found, do not fall back to linear
197
+ if (requestedType !== "linear" && requestedType !== "vibration" && requestedType !== "cubicbezier" && (!Easing || !Easing[requestedType])) {
198
+ // Use Error instead of warn to make it impossible to ignore
199
+ throw new Error(`Select-Animation ERROR: The easing function "${requestedType}" does not exist. Please check your spelling or definitions.`);
200
+ }
201
+ }
202
+ }
203
+
204
+ // Double-check if the animation type is valid before processing
205
+ if (!defsCopy[c].typeAnimation) return;
206
+
207
+ // 2. Helper to sanitize input values (convert "100px" to 100)
208
+ const parseVal = (v) => {
209
+ if (typeof v === "number") return v;
210
+ let p = parseFloat(v);
211
+ return isNaN(p) ? 0 : p;
212
+ };
213
+
214
+ // Process properties and prepare "from" and "to" values
215
+ if (!defsCopy[c].callback &&
216
+ (Array.isArray(defsCopy[c].property) || (defsCopy[c].property !== undefined && (defsCopy[c].property = [defsCopy[c].property])))) {
217
+
218
+ defsCopy[c].property.forEach(function (propItem) {
219
+ const fromIsObject = typeof defsCopy[c].from === "object";
220
+ const toIsObject = typeof defsCopy[c].to === "object";
221
+
222
+ // Safely extract from/to values based on their types
223
+ if (!fromIsObject) valFrom = parseVal(defsCopy[c].from);
224
+ else fromItem = defsCopy[c]["from"][propIndex] || 0;
225
+
226
+ if (!toIsObject) valTo = parseVal(defsCopy[c].to);
227
+ else toItem = defsCopy[c]["to"][propIndex] || 0;
228
+
229
+ if (typeof propItem === "object") {
230
+ let propName = Object.keys(propItem)[0];
231
+ if (!Array.isArray(propItem[propName])) propItem[propName] = [propItem[propName]];
232
+
233
+ // Handle Colors and Transform objects
234
+ if ((propName.toLowerCase().indexOf("color") !== -1 && (staging.color[propName] = COLOR_PROPERTIES[propName])) ||
235
+ propName.toLowerCase().indexOf("transform") !== -1) {
236
+
237
+ let inner = 0;
238
+ staging["from"][propName] = {};
239
+ staging["to"][propName] = {};
240
+
241
+ propItem[propName].forEach(function (innerProp) {
242
+ if (propName.toLowerCase() === "transform") staging[propName][innerProp] = 0;
243
+ else staging.color[propName][innerProp] = 0;
244
+
245
+ // Validate and assign nested properties
246
+ if (fromIsObject) {
247
+ let raw = (fromItem[propName] !== undefined) ? (Array.isArray(fromItem[propName]) ? fromItem[propName][inner] : fromItem[propName][innerProp]) : valFrom;
248
+ staging["from"][propName][innerProp] = parseVal(raw);
249
+ } else {
250
+ staging["from"][propName][innerProp] = parseVal(defsCopy[c].from);
251
+ }
252
+
253
+ if (toIsObject) {
254
+ let raw = (toItem[propName] !== undefined) ? (Array.isArray(toItem[propName]) ? toItem[propName][inner] : toItem[propName][innerProp]) : valTo;
255
+ staging["to"][propName][innerProp] = parseVal(raw);
256
+ } else {
257
+ staging["to"][propName][innerProp] = parseVal(defsCopy[c].to);
258
+ }
259
+ inner++;
260
+ });
261
+ propIndex++;
262
+ }
263
+ } else {
264
+ // Handle simple numeric CSS properties (width, height, etc.)
265
+ if (fromIsObject) {
266
+ let raw = fromItem[propItem] !== undefined ? fromItem[propItem] : (fromItem !== undefined ? fromItem : valFrom);
267
+ staging["from"][propItem] = parseVal(raw);
268
+ } else {
269
+ staging["from"][propItem] = parseVal(defsCopy[c].from);
270
+ }
271
+
272
+ if (toIsObject) {
273
+ let raw = toItem[propItem] !== undefined ? toItem[propItem] : (toItem !== undefined ? toItem : valTo);
274
+ staging["to"][propItem] = parseVal(raw);
275
+ } else {
276
+ staging["to"][propItem] = parseVal(defsCopy[c].to);
277
+ }
278
+ propIndex++;
279
+ }
280
+ });
281
+ }
282
+
283
+ // 3. Callback Safety Validation
284
+ // Ensure hooks are actual functions to prevent execution errors
285
+ if (defsCopy[c].onStep && typeof defsCopy[c].onStep !== 'function') defsCopy[c].onStep = null;
286
+ if (defsCopy[c].onComplete && typeof defsCopy[c].onComplete !== 'function') defsCopy[c].onComplete = null;
287
+
288
+ // Finalize staging data and store it
289
+ defsCopy[c].storeValueAnim = copyObj(staging);
290
+ staging = { color: {}, transform: {}, from: {}, to: {} };
291
+ }
292
+
293
+ // Determine if the next item starts a new sequence group
294
+ if (definitions[c + 1] !== undefined && (Array.isArray(definitions[c + 1]) || isElement(definitions[c + 1]))) {
295
+ expectNextGroup = true;
296
+ grouped = [];
297
+ }
298
+ }
299
+
300
+ // Switch to second pass to execute the runners
301
+ if (c === total - 1 && !secondPass) {
302
+ expectNextGroup = false;
303
+ secondPass = true;
304
+ c = -1;
305
+ }
306
+ }
307
+ }
308
+
309
+ function runner(group, defs, defsCopyLocal, configIndex) {
310
+ const conf = defs[configIndex];
311
+ const declaredAnim = defsCopyLocal[configIndex].typeAnimation;
312
+ let alternateAnim = declaredAnim;
313
+
314
+ // Sanitize timing inputs
315
+ conf.timeline = !isNaN(Number(conf.timeline)) ? Number(conf.timeline) : 0;
316
+ conf.startafter = !isNaN(Number(conf.startafter)) ? Number(conf.startafter) : 0;
317
+
318
+ // Prepare looping and easing alternates
319
+ if (conf.boucle) {
320
+ conf.delay = !isNaN(Number(conf.delay)) ? Number(conf.delay) : undefined;
321
+ if (conf.boucleType === "returnRepeat" || conf.boucleType === "repeatReturn") {
322
+ alternateAnim = Easing[declaredAnim][1];
323
+ }
324
+ }
325
+
326
+ return function run(indexArg) {
327
+ let pausedAccum = 0;
328
+ let isPaused = false;
329
+ let pauseStart;
330
+
331
+ // Initialize event-based pause/resume logic if configured
332
+ if (conf.pause && Array.isArray(conf.pause)) {
333
+ const eventCfg = conf.pause[1] || "e:click|false";
334
+ const parts = eventCfg.replace('e:', '').split('|');
335
+ const eventName = parts[0];
336
+ const useCapture = parts[1] === 'true';
337
+
338
+ const togglePause = function (e) {
339
+ if (e) {
340
+ if (isPaused) {
341
+ isPaused = false;
342
+ pausedAccum += Date.now() - pauseStart;
343
+ } else {
344
+ isPaused = true;
345
+ pauseStart = Date.now();
346
+ }
347
+ }
348
+ };
349
+
350
+ const targetEls = document.querySelectorAll(conf.pause[0]);
351
+ targetEls.forEach(el => el.addEventListener(eventName, togglePause, useCapture));
352
+ }
353
+
354
+ const startedAt = Date.now();
355
+
356
+ // Initialize state storage for each element in the group
357
+ group.forEach(function (el, idx) {
358
+ if (!el.storeTransform) el.storeTransform = copyObj(defsCopyLocal[configIndex].storeValueAnim.transform);
359
+ if (!el.storeColor) {
360
+ el.storeColor = copyObj(defsCopyLocal[configIndex].storeValueAnim.color);
361
+ } else {
362
+ Object.keys(defsCopyLocal[configIndex].storeValueAnim.color).forEach(key => {
363
+ if (!el.storeColor[key]) el.storeColor[key] = defsCopyLocal[configIndex].storeValueAnim.color[key];
364
+ });
365
+ }
366
+
367
+ // Start staggered animations if timeline offset exists
368
+ if (conf.timeline !== 0) {
369
+ frameRunner([el], idx, conf.timeline * idx + conf.startafter, conf.startafter);
370
+ }
371
+ });
372
+
373
+ // Start simultaneous animations
374
+ if (conf.timeline === 0) {
375
+ frameRunner(group, 0, 0 + conf.startafter, conf.startafter);
376
+ }
377
+
378
+ function frameRunner(targetArray, idx, timeOffset, startAfter) {
379
+ // Manage animation frame cycles
380
+ if (conf.animFram) cancelAnimationFrame(conf.animFram[idx]);
381
+ else conf.animFram = {};
382
+
383
+ const iterConf = copyObj(defsCopyLocal[configIndex]);
384
+ iterConf.changetypeAnim = iterConf.typeAnimation;
385
+ iterConf.countSkip = 0;
386
+ iterConf.countSkip2 = 0;
387
+
388
+ let skipCounter;
389
+ const sv = iterConf.storeValueAnim;
390
+
391
+ // The main animation loop using requestAnimationFrame
392
+ function loop() {
393
+ if (isPaused) {
394
+ conf.animFram[idx] = requestAnimationFrame(loop);
395
+ return;
396
+ }
397
+
398
+ let delay = 0;
399
+ let eased, tmpVal, css;
400
+ const elapsed = Date.now() - (startedAt + timeOffset + pausedAccum);
401
+
402
+ if (elapsed >= 0) {
403
+ // Logic for handling loops, delays, and reversing (yoyo) animations
404
+ if (iterConf.boucle) {
405
+ if (iterConf.delay !== undefined) {
406
+ delay = iterConf.delay;
407
+ skipCounter = Math.floor((elapsed + delay) / (iterConf.duration + delay));
408
+ if (skipCounter !== iterConf.countSkip) {
409
+ iterConf.countSkip = skipCounter;
410
+ iterConf.skip = iterConf.skipDelay = true;
411
+ } else {
412
+ iterConf.skip = false;
413
+ if (elapsed % (iterConf.duration + delay) < iterConf.duration) {
414
+ iterConf.skipDelay = false;
415
+ if (iterConf.countSkip2 !== iterConf.countSkip) {
416
+ iterConf.countSkip2 = iterConf.countSkip;
417
+ iterConf.skip2 = true;
418
+ } else iterConf.skip2 = false;
419
+ }
420
+ }
421
+ } else {
422
+ skipCounter = Math.floor((elapsed + delay) / (iterConf.duration + delay));
423
+ if (skipCounter !== iterConf.countSkip) {
424
+ iterConf.countSkip = iterConf.countSkip2 = skipCounter;
425
+ iterConf.skip = iterConf.skip2 = true;
426
+ } else {
427
+ iterConf.skip = iterConf.skip2 = false;
428
+ }
429
+ }
430
+
431
+ iterConf.timeEasing = elapsed % (iterConf.duration + delay);
432
+ if (iterConf.skip) {
433
+ iterConf.impair = !iterConf.impair;
434
+ iterConf.changetypeAnim = iterConf.impair ? alternateAnim : declaredAnim;
435
+ iterConf.timeEasing = (iterConf.impair || iterConf.boucleType.indexOf("repeat") === 0) ? iterConf.duration : 0;
436
+ } else if (!iterConf.skipDelay) {
437
+ if (iterConf.impair && iterConf.boucleType.indexOf("return") === 0) {
438
+ iterConf.timeEasing = iterConf.duration - iterConf.timeEasing;
439
+ }
440
+ }
441
+ } else {
442
+ iterConf.timeEasing = elapsed < iterConf.duration ? elapsed : iterConf.duration;
443
+ }
444
+
445
+ // Update properties if not in delay phase
446
+ if (!iterConf.skipDelay || iterConf.skip) {
447
+ // Calculate ease factor (0 to 1)
448
+ eased = Easing[iterConf.changetypeAnim][0](iterConf.timeEasing, 0, 1, iterConf.duration, iterConf, idx);
449
+
450
+ if (iterConf.callback) {
451
+ targetArray.forEach(function (el, index) {
452
+ iterConf.callback(el, eased, iterConf, idx !== index ? idx : index);
453
+ });
454
+ } else {
455
+ // Apply styles: Transform, Color, or standard Numeric properties
456
+ iterConf.property.forEach(function (prop) {
457
+ css = "";
458
+ let key = typeof prop === "string" ? prop : Object.keys(prop)[0];
459
+
460
+ if (key.toLowerCase() === "transform" && sv[key] != null) {
461
+ prop.transform.forEach(function (tr) {
462
+ tmpVal = sv["from"][key][tr] + eased * (sv["to"][key][tr] - sv["from"][key][tr]);
463
+ targetArray.forEach(el => el.storeTransform[tr] = tmpVal);
464
+ });
465
+ targetArray.forEach(function (el) {
466
+ Object.keys(el.storeTransform).forEach(k => {
467
+ css += " " + PROPERTY_FORMAT_MAP[k].replace("*", el.storeTransform[k]);
468
+ });
469
+ el.style.transform = css;
470
+ css = "";
471
+ });
472
+ } else if (key.toLowerCase().indexOf("color") !== -1 && sv.color != null) {
473
+ targetArray.forEach(function (el) {
474
+ prop[key].forEach(function (colProp) {
475
+ tmpVal = sv["from"][key][colProp] + eased * (sv["to"][key][colProp] - sv["from"][key][colProp]);
476
+ el.storeColor[key][colProp] = tmpVal;
477
+ });
478
+
479
+ let colorStr = PROPERTY_FORMAT_MAP.rgba;
480
+ for (let colKey in COLOR_DEFAULTS) {
481
+ colorStr = colorStr.replace(new RegExp(colKey, "g"), el.storeColor[key][colKey]);
482
+ }
483
+ el.style[key] = colorStr;
484
+ });
485
+ } else {
486
+ css = (iterConf.px === "%" ? PROPERTY_FORMAT_MAP[key].replace("px", "%") : PROPERTY_FORMAT_MAP[key]).replace("*", sv["from"][key] + eased * (sv["to"][key] - sv["from"][key]));
487
+ targetArray.forEach(el => el.style[key] = css);
488
+ }
489
+ });
490
+ }
491
+ }
492
+ }
493
+
494
+ // Continue the loop if animation is still active or looping
495
+ if (iterConf.boucle || elapsed < iterConf.duration) {
496
+ conf.animFram[idx] = requestAnimationFrame(loop);
497
+ }
498
+ }
499
+
500
+ loop();
501
+ }
502
+ };
503
+ }
504
+ };
505
+ };
506
+
507
+ // -----------------------------
508
+ // Easing functions
509
+ // Standard easing definitions used by the animation engine.
510
+ // -----------------------------
511
+ const Easing = {
512
+ linear: [function(e, n, t, a) {
513
+ return t * e / a + n
514
+ }, "linear"],
515
+ quadin: [function(e, n, t, a) {
516
+ return t * (e /= a) * e + n
517
+ }, "quadout"],
518
+ quadout: [function(e, n, t, a) {
519
+ return -t * (e /= a) * (e - 2) + n
520
+ }, "quadin"],
521
+ quadinout: [function(e, n, t, a) {
522
+ return (e /= a / 2) < 1 ? t / 2 * e * e + n : -t / 2 * (--e * (e - 2) - 1) + n
523
+ }, "quadoutin"],
524
+ quadoutin: [function(e, n, t, a) {
525
+ var p = e / a,
526
+ p0;
527
+ if (p < 0.5) {
528
+ p0 = 1 - 2 * p;
529
+ return t * (0.5 * (1 - (p0 * p0))) + n;
530
+ } else {
531
+ p0 = p * 2 - 1;
532
+ return t * (0.5 * (p0 * p0) + 0.5) + n;
533
+ }
534
+ }, "quadinout"],
535
+ cubicin: [function(e, n, t, a) {
536
+ return t * (e /= a) * e * e + n
537
+ }, "cubicout"],
538
+ cubicout: [function(e, n, t, a) {
539
+ return t * ((e = e / a - 1) * e * e + 1) + n
540
+ }, "cubicin"],
541
+ cubicinout: [function(e, n, t, a) {
542
+ return (e /= a / 2) < 1 ? t / 2 * e * e * e + n : t / 2 * ((e -= 2) * e * e + 2) + n
543
+ }, "cubicoutin"],
544
+ cubicoutin: [function(e, n, t, a) {
545
+ var p = e / a,
546
+ p0;
547
+ if (p < 0.5) {
548
+ p0 = 1 - 2 * p;
549
+ return t * (0.5 * (1 - (p0 * p0 * p0))) + n;
550
+ } else {
551
+ p0 = p * 2 - 1;
552
+ return t * (0.5 * (p0 * p0 * p0) + 0.5) + n;
553
+ }
554
+ }, "cubicinout"],
555
+ quartin: [function(e, n, t, a) {
556
+ return t * (e /= a) * e * e * e + n
557
+ }, "quartout"],
558
+ quartout: [function(e, n, t, a) {
559
+ return -t * ((e = e / a - 1) * e * e * e - 1) + n
560
+ }, "quartin"],
561
+ quartinout: [function(e, n, t, a) {
562
+ return (e /= a / 2) < 1 ? t / 2 * e * e * e * e + n : -t / 2 * ((e -= 2) * e * e * e - 2) + n
563
+ }, "quartoutin"],
564
+ quartoutin: [function(e, n, t, a) {
565
+ var p = e / a,
566
+ p0;
567
+ if (p < 0.5) {
568
+ p0 = 1 - 2 * p;
569
+ return t * (0.5 * (1 - (p0 * p0 * p0 * p0))) + n;
570
+ } else {
571
+ p0 = p * 2 - 1;
572
+ return t * (0.5 * (p0 * p0 * p0 * p0) + 0.5) + n;
573
+ }
574
+ }, "quartinout"],
575
+ quintin: [function(e, n, t, a) {
576
+ return t * (e /= a) * e * e * e * e + n
577
+ }, "quintout"],
578
+ quintout: [function(e, n, t, a) {
579
+ return t * ((e = e / a - 1) * e * e * e * e + 1) + n
580
+ }, "quintin"],
581
+ quintinout: [function(e, n, t, a) {
582
+ return (e /= a / 2) < 1 ? t / 2 * e * e * e * e * e + n : t / 2 * ((e -= 2) * e * e * e * e + 2) + n
583
+ }, "quintoutin"],
584
+ quintoutin: [function(e, n, t, a) {
585
+ var p = e / a,
586
+ p0;
587
+ if (p < 0.5) {
588
+ p0 = 1 - 2 * p;
589
+ return t * (0.5 * (1 - (p0 * p0 * p0 * p0 * p0))) + n;
590
+ } else {
591
+ p0 = p * 2 - 1;
592
+ return t * (0.5 * (p0 * p0 * p0 * p0 * p0) + 0.5) + n;
593
+ }
594
+ }, "quintinout"],
595
+ sinein: [function(e, n, t, a) {
596
+ return -t * Math.cos(e / a * (Math.PI / 2)) + t + n
597
+ }, "sineout"],
598
+ sineout: [function(e, n, t, a) {
599
+ return t * Math.sin(e / a * (Math.PI / 2)) + n
600
+ }, "sinein"],
601
+ sineinout: [function(e, n, t, a) {
602
+ return -t / 2 * (Math.cos(Math.PI * e / a) - 1) + n
603
+ }, "sineoutin"],
604
+ sineoutin: [function(e, n, t, a) {
605
+ var p = e / a,
606
+ p0;
607
+ if (p < 0.5) {
608
+ p0 = 1 - 2 * p;
609
+ return t * (0.5 * (1 - (1 - Math.cos(p0 * Math.PI / 2)))) + n;
610
+ } else {
611
+ p0 = p * 2 - 1;
612
+ return t * (0.5 * (1 - Math.cos(p0 * Math.PI / 2)) + 0.5) + n;
613
+ }
614
+ }, "sineinout"],
615
+ expoin: [function(e, n, t, a) {
616
+ return 0 == e ? n : t * Math.pow(2, 10 * (e / a - 1)) + n
617
+ }, "expoout"],
618
+ expoout: [function(e, n, t, a) {
619
+ return e == a ? n + t : t * (1 - Math.pow(2, -10 * e / a)) + n
620
+ }, "expoin"],
621
+ expoinout: [function(e, n, t, a) {
622
+ return 0 == e ? n : e == a ? n + t : (e /= a / 2) < 1 ? t / 2 * Math.pow(2, 10 * (e - 1)) + n : t / 2 * (2 - Math.pow(2, -10 * --e)) + n
623
+ }, "expooutin"],
624
+ expooutin: [function(e, n, t, a) {
625
+ var p = e / a,
626
+ p0;
627
+ if (p == 0) {
628
+ return n;
629
+ } else if (p == 1) {
630
+ return n + t;
631
+ } else
632
+ if (p < 0.5) {
633
+ p0 = 1 - 2 * p;
634
+ return t * (0.5 * (1 - (Math.pow(2, 10 * (p0 - 1))))) + n;
635
+ } else {
636
+ p0 = p * 2 - 1;
637
+ return t * (0.5 * (Math.pow(2, 10 * (p0 - 1))) + 0.5) + n;
638
+ }
639
+ }, "expoinout"],
640
+ circin: [function(e, n, t, a) {
641
+ return -t * (Math.sqrt(1 - (e /= a) * e) - 1) + n
642
+ }, "circout"],
643
+ circout: [function(e, n, t, a) {
644
+ return t * Math.sqrt(1 - (e = e / a - 1) * e) + n
645
+ }, "circin"],
646
+ circinout: [function(e, n, t, a) {
647
+ return (e /= a / 2) < 1 ? -t / 2 * (Math.sqrt(1 - e * e) - 1) + n : t / 2 * (Math.sqrt(1 - (e -= 2) * e) + 1) + n
648
+ }, "circoutin"],
649
+ circoutin: [function(e, n, t, a) {
650
+ var p = e / a,
651
+ p0;
652
+ if (p < 0.5) {
653
+ p0 = 1 - 2 * p;
654
+ return t * (0.5 * Math.sqrt(1 - p0 * p0)) + n;
655
+ } else {
656
+ p0 = p * 2 - 1;
657
+ return t * (0.5 * (1 - Math.sqrt(1 - p0 * p0)) + 0.5) + n;
658
+ }
659
+ }, "circinout"],
660
+ elasticin: [function(e, n, t, a) {
661
+ var c = 1.70158,
662
+ b = 0,
663
+ r = t;
664
+ return 0 == e ? n : 1 == (e /= a) ? n + t : (b = b || .3 * a, c = r < Math.abs(t) ? (r = t, b / 4) : b / (2 * Math.PI) * Math.asin(t / r), -(r * Math.pow(2, 10 * --e) * Math.sin((e * a - c) * (2 * Math.PI) / b)) + n)
665
+ }, "elasticout"],
666
+ elasticout: [function(e, n, t, a) {
667
+ var c = 1.70158,
668
+ b = 0,
669
+ r = t;
670
+ return 0 == e ? n : 1 == (e /= a) ? n + t : (b = b || .3 * a, c = r < Math.abs(t) ? (r = t, b / 4) : b / (2 * Math.PI) * Math.asin(t / r), r * Math.pow(2, -10 * e) * Math.sin((e * a - c) * (2 * Math.PI) / b) + t + n)
671
+ }, "elasticin"],
672
+ elasticinout: [function(e, n, t, a) {
673
+ var c = 1.70158,
674
+ b = 0,
675
+ r = t;
676
+ return 0 == e ? n : 2 == (e /= a / 2) ? n + t : (b = b || a * (.3 * 1.5), c = r < Math.abs(t) ? (r = t, b / 4) : b / (2 * Math.PI) * Math.asin(t / r), e < 1 ? r * Math.pow(2, 10 * --e) * Math.sin((e * a - c) * (2 * Math.PI) / b) * -.5 + n : r * Math.pow(2, -10 * --e) * Math.sin((e * a - c) * (2 * Math.PI) / b) * .5 + t + n)
677
+ }, "elasticoutin"],
678
+ elasticoutin: [function(e, n, t, a) {
679
+ var p = e / a,
680
+ p0;
681
+ if (p === 0) {
682
+ return n;
683
+ } else if (p === 1) {
684
+ return t + n;
685
+ }
686
+ if (p < 0.5) {
687
+ p0 = 1 - 2 * p;
688
+ return t * (0.5 * (1 - (-Math.pow(2, 8 * (p0 - 1)) * Math.sin(((p0 - 1) * 80 - 7.5) * Math.PI / 15)))) + n;
689
+ } else {
690
+ p0 = p * 2 - 1;
691
+ return t * (0.5 * (-Math.pow(2, 8 * (p0 - 1)) * Math.sin(((p0 - 1) * 80 - 7.5) * Math.PI / 15)) + 0.5) + n
692
+ }
693
+ }, "elasticinout"],
694
+ backin: [function(e, n, t, a) {
695
+ return t * (e /= a) * e * (2.70158 * e - 1.70158) + n
696
+ }, "backout"],
697
+ backout: [function(e, n, t, a) {
698
+ return t * ((e = e / a - 1) * e * (2.70158 * e + 1.70158) + 1) + n
699
+ }, "backin"],
700
+ backinout: [function(e, n, t, a) {
701
+ var c = 1.70158;
702
+ return (e /= a / 2) < 1 ? t / 2 * (e * e * ((1 + (c *= 1.525)) * e - c)) + n : t / 2 * ((e -= 2) * e * ((1 + (c *= 1.525)) * e + c) + 2) + n
703
+ }, "backoutin"],
704
+ backoutin: [function(e, n, t, a) {
705
+ var p = e / a,
706
+ p0;
707
+ if (p < 0.5) {
708
+ p0 = 1 - 2 * p;
709
+ return t * (0.5 * (1 - p0 * p0 * (3 * p0 - 2))) + n;
710
+ } else {
711
+ p0 = p * 2 - 1;
712
+ return t * (0.5 * p0 * p0 * (3 * p0 - 2) + 0.5) + n;
713
+ }
714
+ }, "backinout"],
715
+ bouncein: [function(e, n, t, a) {
716
+ return t - Easing.bounceout[0](a - e, 0, t, a) + n
717
+ }, "bounceout"],
718
+ bounceout: [function(e, n, t, a) {
719
+ return (e /= a) < 1 / 2.75 ? t * (7.5625 * e * e) + n : e < 2 / 2.75 ? t * (7.5625 * (e -= 1.5 / 2.75) * e + .75) + n : e < 2.5 / 2.75 ? t * (7.5625 * (e -= 2.25 / 2.75) * e + .9375) + n : t * (7.5625 * (e -= 2.625 / 2.75) * e + .984375) + n
720
+ }, "bouncein"],
721
+ bounceinout: [function(e, n, t, a) {
722
+ return e < a / 2 ? .5 * Easing.bouncein[0](2 * e, 0, t, a) + n : .5 * Easing.bounceout[0](2 * e - a, 0, t, a) + .5 * t + n
723
+ }, "bounceoutin"],
724
+ bounceoutin: [function(e, n, t, a) {
725
+ var p = e / a,
726
+ p0, pow2, bounce = 4;
727
+ if (p < 0.5) {
728
+ p0 = 1 - 2 * p;
729
+ while (p0 < ((pow2 = Math.pow(2, --bounce)) - 1) / 11) {}
730
+ return t * (0.5 * (1 - (1 / Math.pow(4, 3 - bounce) - 7.5625 * Math.pow((pow2 * 3 - 2) / 22 - p0, 2)))) + n;
731
+ } else {
732
+ p0 = p * 2 - 1;
733
+ while (p0 < ((pow2 = Math.pow(2, --bounce)) - 1) / 11) {}
734
+ return t * (0.5 * (1 / Math.pow(4, 3 - bounce) - 7.5625 * Math.pow((pow2 * 3 - 2) / 22 - p0, 2)) + 0.5) + n;
735
+ }
736
+ }, "bounceinout"],
737
+ vibration: [function(e, n, t, a, c) {
738
+ return n + (t - n) / 2 + Math.sin(e * Math.PI / (a / c.vibrationStep) + 3 * Math.PI / 2) * (t - n) / 2
739
+ }, "vibration"],
740
+ cubicbezier: [function(e, n, t, a, c) {
741
+ let q = 1, qq = 0, sol;
742
+ if (c.impair && (c.boucleType === "returnRepeat" || c.boucleType === "repeatReturn")) {
743
+ q = -1; qq = 1;
744
+ }
745
+ let b = e / a, r = 1 - b,
746
+ l = Number(q * c.cubicbezier[0] + qq),
747
+ o = Number(q * c.cubicbezier[2] + qq);
748
+
749
+ if ((sol = solveCubic(3 * l - 3 * o + 1, 0 - 6 * l + 3 * o, 3 * l, 0 - b))) {
750
+ b = sol;
751
+ r = 1 - b;
752
+ }
753
+ let y = (r = 1 - b) * r * r * 0 + 3 * r * r * b * Number(q * c.cubicbezier[1] + qq) + 3 * r * b * b * Number(q * c.cubicbezier[3] + qq) + b * b * b * 1;
754
+ return n + y * t;
755
+ }, "cubicbezier"]
756
+ };
757
+
758
+ // The rest of easing functions identical to original (unchanged for correctness)
759
+ // (For brevity in this file view we keep the full Easing object above in the same form as original.)
760
+
761
+ // -----------------------------
762
+ // Math helpers: cubic solver and cube root
763
+ // -----------------------------
764
+ function solveCubic(a, b, c, d) {
765
+ let p = (3 * a * c - b * b) / (3 * a * a);
766
+ let q = (2 * b * b * b - 9 * a * b * c + 27 * a * a * d) / (27 * a * a * a);
767
+ let r;
768
+
769
+ if (Math.abs(p) < 1e-8) {
770
+ if ((r = cubeRoot(-q) - b / (3 * a)) <= 1 && r >= 0) return r;
771
+ } else if (Math.abs(q) < 1e-8) {
772
+ if (((r = Math.sqrt(-p) - b / (3 * a)) <= 1 && r >= 0) || ((r = -Math.sqrt(-p) - b / (3 * a)) <= 1 && r >= 0)) return r;
773
+ else return 0;
774
+ } else {
775
+ let D = q * q / 4 + p * p * p / 27;
776
+ if (Math.abs(D) < 1e-8) {
777
+ if (((r = -1.5 * q / p - b / (3 * a)) <= 1 && r >= 0) || ((r = 3 * q / p - b / (3 * a)) <= 1 && r >= 0)) return r;
778
+ } else if (D > 0) {
779
+ let u = cubeRoot(-q / 2 - Math.sqrt(D));
780
+ if ((r = (u - p / (3 * u)) - b / (3 * a)) <= 1 && r >= 0) return r;
781
+ } else {
782
+ let u = 2 * Math.sqrt(-p / 3);
783
+ let t = Math.acos(3 * q / p / u) / 3;
784
+ let k = 2 * Math.PI / 3;
785
+ if (((r = u * Math.cos(t) - b / (3 * a)) <= 1 && r >= 0) || ((r = u * Math.cos(t - k) - b / (3 * a)) <= 1 && r >= 0) || ((r = u * Math.cos(t - 2 * k) - b / (3 * a)) <= 1 && r >= 0)) return r;
786
+ }
787
+ }
788
+ }
789
+
790
+ function cubeRoot(v) {
791
+ let n = Math.pow(Math.abs(v), 1 / 3);
792
+ return v < 0 ? -n : n;
793
+ }
794
+
795
+ // -----------------------------
796
+ // Utilities: getNumber, getStyle, isElement, copyObj
797
+ // -----------------------------
798
+ function getNumber(str) {
799
+ return (str || '').match(/[+-]?\d+(\.\d+)?/g);
800
+ }
801
+
802
+ function getStyle(el, cssprop) {
803
+ if (el.currentStyle) return el.currentStyle[cssprop];
804
+ else if (document.defaultView && document.defaultView.getComputedStyle) return document.defaultView.getComputedStyle(el, "")[cssprop];
805
+ else return el.style[cssprop];
806
+ }
807
+
808
+ // --- Robust DOM Element Validation ---
809
+ function isElement(element) {
810
+ try {
811
+ // Check for standard DOM Element or HTMLDocument
812
+ return element instanceof Element || element instanceof HTMLDocument;
813
+ } catch (e) {
814
+ // Fallback for environments where Element is not defined
815
+ return (typeof element === "object") &&
816
+ (element.nodeType === 1) &&
817
+ (typeof element.nodeName === "string");
818
+ }
819
+ }
820
+
821
+ const copyObj = function(obj) {
822
+ let ret;
823
+ const assign = function(o, key, target) {
824
+ let sub = Object.prototype.toString.call(o[key]);
825
+ if (sub === "[object Object]" || sub === "[object Array]") {
826
+ target[key] = copyObj(o[key]);
827
+ } else {
828
+ target[key] = o[key];
829
+ }
830
+ };
831
+
832
+ if (Object.prototype.toString.call(obj) === "[object Object]") {
833
+ ret = {};
834
+ for (let key in obj) {
835
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
836
+ assign(obj, key, ret);
837
+ }
838
+ }
839
+ } else if (Object.prototype.toString.call(obj) === "[object Array]") {
840
+ ret = [];
841
+ for (let i = 0; i < obj.length; i++) {
842
+ assign(obj, i, ret);
843
+ }
844
+ } else {
845
+ ret = obj;
846
+ }
847
+ return ret;
848
+ };
849
+
850
+ // Expose both for browser and Node/npm consumers
851
+ if (typeof module !== 'undefined' && module.exports) {
852
+ module.exports = {
853
+ animate,
854
+ selectDom,
855
+ copyObj
856
+ };
857
+ }
858
+
859
+ if (typeof global !== 'undefined') {
860
+ global.animate = animate;
861
+ global.selectDom = selectDom;
862
+ global.copyObj = copyObj;
863
+ }
864
+
865
+ })(typeof window !== 'undefined' ? window : this);