@studiometa/js-toolkit 2.0.1 → 2.2.0-alpha.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.
- package/Base/index.cjs +55 -18
- package/Base/index.d.ts +23 -1
- package/Base/index.js +55 -18
- package/Base/managers/AbstractManager.cjs +56 -0
- package/Base/managers/AbstractManager.d.ts +44 -0
- package/Base/managers/AbstractManager.js +35 -0
- package/Base/managers/ChildrenManager.cjs +79 -100
- package/Base/managers/ChildrenManager.d.ts +7 -82
- package/Base/managers/ChildrenManager.js +76 -100
- package/Base/managers/EventsManager.cjs +75 -99
- package/Base/managers/EventsManager.d.ts +31 -100
- package/Base/managers/EventsManager.js +75 -99
- package/Base/managers/OptionsManager.cjs +65 -78
- package/Base/managers/OptionsManager.d.ts +37 -79
- package/Base/managers/OptionsManager.js +66 -79
- package/Base/managers/RefsManager.cjs +44 -68
- package/Base/managers/RefsManager.d.ts +10 -64
- package/Base/managers/RefsManager.js +41 -69
- package/Base/managers/ResponsiveOptionsManager.cjs +62 -0
- package/Base/managers/ResponsiveOptionsManager.d.ts +26 -0
- package/Base/managers/ResponsiveOptionsManager.js +37 -0
- package/Base/managers/ServicesManager.cjs +5 -11
- package/Base/managers/ServicesManager.d.ts +2 -11
- package/Base/managers/ServicesManager.js +5 -11
- package/decorators/index.cjs +2 -0
- package/decorators/index.d.ts +1 -0
- package/decorators/index.js +6 -4
- package/decorators/withResponsiveOptions.cjs +39 -0
- package/decorators/withResponsiveOptions.d.ts +8 -0
- package/decorators/withResponsiveOptions.js +14 -0
- package/decorators/withScrolledInView.cjs +66 -23
- package/decorators/withScrolledInView.d.ts +4 -2
- package/decorators/withScrolledInView.js +67 -24
- package/package.json +2 -1
- package/services/Service.cjs +2 -2
- package/services/Service.d.ts +9 -1
- package/services/Service.js +2 -2
- package/services/raf.cjs +16 -0
- package/services/raf.js +16 -0
- package/utils/css/animate.cjs +207 -0
- package/utils/css/animate.d.ts +57 -0
- package/utils/css/animate.js +182 -0
- package/utils/css/getOffsetSizes.cjs +47 -0
- package/utils/css/getOffsetSizes.d.ts +15 -0
- package/utils/css/getOffsetSizes.js +25 -0
- package/utils/css/index.cjs +6 -0
- package/utils/css/index.d.ts +3 -0
- package/utils/css/index.js +9 -4
- package/utils/css/transform.cjs +91 -0
- package/utils/css/transform.d.ts +43 -0
- package/utils/css/transform.js +66 -0
- package/utils/index.cjs +5 -0
- package/utils/index.d.ts +3 -0
- package/utils/index.js +5 -0
- package/utils/isDefined.cjs +28 -0
- package/utils/isDefined.d.ts +7 -0
- package/utils/isDefined.js +6 -0
- package/utils/isFunction.cjs +28 -0
- package/utils/isFunction.d.ts +7 -0
- package/utils/isFunction.js +6 -0
- package/utils/math/index.cjs +2 -0
- package/utils/math/index.d.ts +1 -0
- package/utils/math/index.js +2 -0
- package/utils/scheduler.cjs +73 -0
- package/utils/scheduler.d.ts +19 -0
- package/utils/scheduler.js +51 -0
|
@@ -5,12 +5,13 @@ var __publicField = (obj, key, value) => {
|
|
|
5
5
|
return value;
|
|
6
6
|
};
|
|
7
7
|
import withMountWhenInView from "./withMountWhenInView.js";
|
|
8
|
-
import { damp, clamp, clamp01 } from "../utils/index.js";
|
|
9
|
-
|
|
8
|
+
import { damp, clamp, clamp01, getOffsetSizes, isFunction, useScheduler } from "../utils/index.js";
|
|
9
|
+
const scheduler = useScheduler(["update", "render"]);
|
|
10
|
+
function withScrolledInView(BaseClass, options = {}) {
|
|
10
11
|
var _a;
|
|
11
12
|
return _a = class extends withMountWhenInView(BaseClass, options) {
|
|
12
|
-
constructor() {
|
|
13
|
-
super(
|
|
13
|
+
constructor(element) {
|
|
14
|
+
super(element);
|
|
14
15
|
__publicField(this, "__props", {
|
|
15
16
|
start: {
|
|
16
17
|
x: 0,
|
|
@@ -35,37 +36,79 @@ function withScrolledInView(BaseClass, options) {
|
|
|
35
36
|
});
|
|
36
37
|
__publicField(this, "dampFactor", 0.1);
|
|
37
38
|
__publicField(this, "dampPrecision", 1e-3);
|
|
39
|
+
const delegate = {
|
|
40
|
+
handleEvent(event) {
|
|
41
|
+
delegate[event.type](event.detail[0]);
|
|
42
|
+
},
|
|
43
|
+
resized: () => {
|
|
44
|
+
this.__setProps();
|
|
45
|
+
},
|
|
46
|
+
scrolled: (props) => {
|
|
47
|
+
if (!this.$services.has("ticked") && props.changed.y || props.changed.x) {
|
|
48
|
+
this.$services.enable("ticked");
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
ticked: () => {
|
|
52
|
+
this.__props.current.x = clamp(window.pageXOffset, this.__props.start.x, this.__props.end.x);
|
|
53
|
+
this.__props.progress.x = clamp01((this.__props.current.x - this.__props.start.x) / (this.__props.end.x - this.__props.start.x));
|
|
54
|
+
this.__props.dampedProgress.x = damp(this.__props.progress.x, this.__props.dampedProgress.x, this.dampFactor, this.dampPrecision);
|
|
55
|
+
this.__props.current.y = clamp(window.pageYOffset, this.__props.start.y, this.__props.end.y);
|
|
56
|
+
this.__props.progress.y = clamp01((this.__props.current.y - this.__props.start.y) / (this.__props.end.y - this.__props.start.y));
|
|
57
|
+
this.__props.dampedProgress.y = damp(this.__props.progress.y, this.__props.dampedProgress.y, this.dampFactor, this.dampPrecision);
|
|
58
|
+
if (this.__props.dampedProgress.x === this.__props.progress.x && this.__props.dampedProgress.y === this.__props.progress.y) {
|
|
59
|
+
this.$services.disable("ticked");
|
|
60
|
+
}
|
|
61
|
+
scheduler.update(() => {
|
|
62
|
+
const renderFn = this.__callMethod("scrolledInView", this.__props);
|
|
63
|
+
if (isFunction(renderFn)) {
|
|
64
|
+
scheduler.render(() => {
|
|
65
|
+
renderFn(this.__props);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
this.$on("before-mounted", () => {
|
|
72
|
+
this.$on("resized", delegate);
|
|
73
|
+
this.$on("scrolled", delegate);
|
|
74
|
+
this.$on("ticked", delegate);
|
|
75
|
+
});
|
|
76
|
+
this.$on("mounted", () => {
|
|
77
|
+
this.__setProps();
|
|
78
|
+
});
|
|
79
|
+
this.$on("destroyed", () => {
|
|
80
|
+
this.$off("resized", delegate);
|
|
81
|
+
this.$off("scrolled", delegate);
|
|
82
|
+
this.$off("ticked", delegate);
|
|
83
|
+
});
|
|
38
84
|
}
|
|
39
85
|
mounted() {
|
|
40
|
-
|
|
86
|
+
if (isFunction(super.mounted))
|
|
87
|
+
super.mounted();
|
|
41
88
|
}
|
|
42
|
-
resized() {
|
|
43
|
-
|
|
89
|
+
resized(props) {
|
|
90
|
+
if (isFunction(super.resized))
|
|
91
|
+
super.resized(props);
|
|
44
92
|
}
|
|
45
93
|
scrolled(props) {
|
|
46
|
-
if (
|
|
47
|
-
|
|
48
|
-
|
|
94
|
+
if (isFunction(super.scrolled))
|
|
95
|
+
super.scrolled(props);
|
|
96
|
+
}
|
|
97
|
+
ticked(props) {
|
|
98
|
+
if (isFunction(super.ticked))
|
|
99
|
+
super.ticked(props);
|
|
49
100
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
this.__props.dampedProgress.x = damp(this.__props.progress.x, this.__props.dampedProgress.x, this.dampFactor, this.dampPrecision);
|
|
54
|
-
this.__props.current.y = clamp(window.pageYOffset, this.__props.start.y, this.__props.end.y);
|
|
55
|
-
this.__props.progress.y = clamp01((this.__props.current.y - this.__props.start.y) / (this.__props.end.y - this.__props.start.y));
|
|
56
|
-
this.__props.dampedProgress.y = damp(this.__props.progress.y, this.__props.dampedProgress.y, this.dampFactor, this.dampPrecision);
|
|
57
|
-
if (this.__props.dampedProgress.x === this.__props.progress.x && this.__props.dampedProgress.y === this.__props.progress.y) {
|
|
58
|
-
this.$services.disable("ticked");
|
|
59
|
-
}
|
|
60
|
-
this.__callMethod("scrolledInView", this.__props);
|
|
101
|
+
destroyed() {
|
|
102
|
+
if (isFunction(super.destroyed))
|
|
103
|
+
super.destroyed();
|
|
61
104
|
}
|
|
62
105
|
__setProps() {
|
|
63
|
-
const sizes = this.$el.getBoundingClientRect();
|
|
64
|
-
const yEnd = sizes.
|
|
106
|
+
const sizes = options.useOffsetSizes ? getOffsetSizes(this.$el) : this.$el.getBoundingClientRect();
|
|
107
|
+
const yEnd = sizes.y + window.pageYOffset + sizes.height;
|
|
65
108
|
const yStart = yEnd - window.innerHeight - sizes.height;
|
|
66
109
|
const yCurrent = clamp(window.pageYOffset, yStart, yEnd);
|
|
67
110
|
const yProgress = clamp01((yCurrent - yStart) / (yEnd - yStart));
|
|
68
|
-
const xEnd = sizes.
|
|
111
|
+
const xEnd = sizes.x + window.pageXOffset + sizes.width;
|
|
69
112
|
const xStart = xEnd - window.innerWidth - sizes.width;
|
|
70
113
|
const xCurrent = clamp(window.pageXOffset, xStart, xEnd);
|
|
71
114
|
const xProgress = clamp01((xCurrent - xStart) / (xEnd - xStart));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@studiometa/js-toolkit",
|
|
3
|
-
"version": "2.0.1",
|
|
3
|
+
"version": "2.2.0-alpha.1",
|
|
4
4
|
"description": "A set of useful little bits of JavaScript to boost your project! 🚀",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
"toolkit"
|
|
40
40
|
],
|
|
41
41
|
"dependencies": {
|
|
42
|
+
"@motionone/easing": "^10.8.0",
|
|
42
43
|
"deepmerge": "^4.2.2"
|
|
43
44
|
}
|
|
44
45
|
}
|
package/services/Service.cjs
CHANGED
|
@@ -29,9 +29,9 @@ __export(Service_exports, {
|
|
|
29
29
|
module.exports = __toCommonJS(Service_exports);
|
|
30
30
|
var Service = class {
|
|
31
31
|
constructor() {
|
|
32
|
+
__publicField(this, "callbacks", /* @__PURE__ */ new Map());
|
|
33
|
+
__publicField(this, "isInit", false);
|
|
32
34
|
__publicField(this, "props");
|
|
33
|
-
this.callbacks = /* @__PURE__ */ new Map();
|
|
34
|
-
this.isInit = false;
|
|
35
35
|
}
|
|
36
36
|
updateProps(...args) {
|
|
37
37
|
this.props = args;
|
package/services/Service.d.ts
CHANGED
|
@@ -2,7 +2,15 @@
|
|
|
2
2
|
* Service abstract class
|
|
3
3
|
*/
|
|
4
4
|
export default class Service {
|
|
5
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Map containing the callbacks.
|
|
7
|
+
* @type {Map<string, Function>}
|
|
8
|
+
*/
|
|
9
|
+
callbacks: Map<string, Function>;
|
|
10
|
+
/**
|
|
11
|
+
* State flag.
|
|
12
|
+
* @type {boolean}
|
|
13
|
+
*/
|
|
6
14
|
isInit: boolean;
|
|
7
15
|
/**
|
|
8
16
|
* @type {unknown}
|
package/services/Service.js
CHANGED
|
@@ -6,9 +6,9 @@ var __publicField = (obj, key, value) => {
|
|
|
6
6
|
};
|
|
7
7
|
class Service {
|
|
8
8
|
constructor() {
|
|
9
|
+
__publicField(this, "callbacks", /* @__PURE__ */ new Map());
|
|
10
|
+
__publicField(this, "isInit", false);
|
|
9
11
|
__publicField(this, "props");
|
|
10
|
-
this.callbacks = /* @__PURE__ */ new Map();
|
|
11
|
-
this.isInit = false;
|
|
12
12
|
}
|
|
13
13
|
updateProps(...args) {
|
|
14
14
|
this.props = args;
|
package/services/raf.cjs
CHANGED
|
@@ -32,6 +32,9 @@ __export(raf_exports, {
|
|
|
32
32
|
module.exports = __toCommonJS(raf_exports);
|
|
33
33
|
var import_Service = __toESM(require("./Service.cjs"), 1);
|
|
34
34
|
var import_nextFrame = require("../utils/nextFrame.cjs");
|
|
35
|
+
var import_scheduler = require("../utils/scheduler.cjs");
|
|
36
|
+
var import_isFunction = __toESM(require("../utils/isFunction.cjs"), 1);
|
|
37
|
+
var scheduler = (0, import_scheduler.useScheduler)(["update", "render"]);
|
|
35
38
|
var Raf = class extends import_Service.default {
|
|
36
39
|
constructor() {
|
|
37
40
|
super(...arguments);
|
|
@@ -63,6 +66,19 @@ var Raf = class extends import_Service.default {
|
|
|
63
66
|
this.props.time = window.performance.now();
|
|
64
67
|
return this.props;
|
|
65
68
|
}
|
|
69
|
+
trigger(...args) {
|
|
70
|
+
this.callbacks.forEach(function forEachCallback(callback) {
|
|
71
|
+
scheduler.update(function rafUpdate() {
|
|
72
|
+
const render = callback(...args);
|
|
73
|
+
if ((0, import_isFunction.default)(render)) {
|
|
74
|
+
scheduler.render(function rafRender() {
|
|
75
|
+
render(...args);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
return this;
|
|
81
|
+
}
|
|
66
82
|
};
|
|
67
83
|
var instance;
|
|
68
84
|
var raf;
|
package/services/raf.js
CHANGED
|
@@ -6,6 +6,9 @@ var __publicField = (obj, key, value) => {
|
|
|
6
6
|
};
|
|
7
7
|
import Service from "./Service.js";
|
|
8
8
|
import { getRaf, getCancelRaf } from "../utils/nextFrame.js";
|
|
9
|
+
import { useScheduler } from "../utils/scheduler.js";
|
|
10
|
+
import isFunction from "../utils/isFunction.js";
|
|
11
|
+
const scheduler = useScheduler(["update", "render"]);
|
|
9
12
|
class Raf extends Service {
|
|
10
13
|
constructor() {
|
|
11
14
|
super(...arguments);
|
|
@@ -37,6 +40,19 @@ class Raf extends Service {
|
|
|
37
40
|
this.props.time = window.performance.now();
|
|
38
41
|
return this.props;
|
|
39
42
|
}
|
|
43
|
+
trigger(...args) {
|
|
44
|
+
this.callbacks.forEach(function forEachCallback(callback) {
|
|
45
|
+
scheduler.update(function rafUpdate() {
|
|
46
|
+
const render = callback(...args);
|
|
47
|
+
if (isFunction(render)) {
|
|
48
|
+
scheduler.render(function rafRender() {
|
|
49
|
+
render(...args);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
return this;
|
|
55
|
+
}
|
|
40
56
|
}
|
|
41
57
|
let instance;
|
|
42
58
|
let raf;
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod));
|
|
20
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
21
|
+
|
|
22
|
+
// packages/js-toolkit/utils/css/animate.js
|
|
23
|
+
var animate_exports = {};
|
|
24
|
+
__export(animate_exports, {
|
|
25
|
+
animate: () => animate
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(animate_exports);
|
|
28
|
+
var import_easing = require("@motionone/easing");
|
|
29
|
+
var import_math = require("../math/index.cjs");
|
|
30
|
+
var import_isDefined = __toESM(require("../isDefined.cjs"), 1);
|
|
31
|
+
var import_transform = __toESM(require("./transform.cjs"), 1);
|
|
32
|
+
var import_raf = __toESM(require("../../services/raf.cjs"), 1);
|
|
33
|
+
var import_scheduler = require("../scheduler.cjs");
|
|
34
|
+
var id = 0;
|
|
35
|
+
var running = /* @__PURE__ */ new WeakMap();
|
|
36
|
+
var raf = (0, import_raf.default)();
|
|
37
|
+
var noop = () => {
|
|
38
|
+
};
|
|
39
|
+
var PROGRESS_PRECISION = 1e-4;
|
|
40
|
+
var CSSUnitConverter = {
|
|
41
|
+
"%": (value, getSizeRef) => value * getSizeRef() / 100,
|
|
42
|
+
vh: (value) => value * window.innerHeight / 100,
|
|
43
|
+
vw: (value) => value * window.innerWidth / 100,
|
|
44
|
+
vmin: (value) => value * Math.min(window.innerWidth, window.innerHeight) / 100,
|
|
45
|
+
vmax: (value) => value * Math.max(window.innerWidth, window.innerHeight) / 100
|
|
46
|
+
};
|
|
47
|
+
function getAnimationStepValue(val, getSizeRef) {
|
|
48
|
+
if (typeof val === "number") {
|
|
49
|
+
return val;
|
|
50
|
+
}
|
|
51
|
+
if (!val[1] || !CSSUnitConverter[val[1]]) {
|
|
52
|
+
return val[0];
|
|
53
|
+
}
|
|
54
|
+
return CSSUnitConverter[val[1]](val[0], getSizeRef);
|
|
55
|
+
}
|
|
56
|
+
function linear(value) {
|
|
57
|
+
return value;
|
|
58
|
+
}
|
|
59
|
+
function normalizeEase(ease) {
|
|
60
|
+
if (!(0, import_isDefined.default)(ease)) {
|
|
61
|
+
return linear;
|
|
62
|
+
}
|
|
63
|
+
if (Array.isArray(ease)) {
|
|
64
|
+
return (0, import_easing.cubicBezier)(...ease);
|
|
65
|
+
}
|
|
66
|
+
return ease;
|
|
67
|
+
}
|
|
68
|
+
var generateTranslateRenderStrategy = (sizeRef) => (element, fromValue, toValue, progress) => (0, import_math.lerp)(getAnimationStepValue(fromValue != null ? fromValue : 0, () => element[sizeRef]), getAnimationStepValue(toValue != null ? toValue : 0, () => element[sizeRef]), progress);
|
|
69
|
+
var widthBasedTranslateRenderStrategy = generateTranslateRenderStrategy("offsetWidth");
|
|
70
|
+
var heightBasedTranslateRenderStrategy = generateTranslateRenderStrategy("offsetHeight");
|
|
71
|
+
var generateLerpRenderStrategy = (defaultValue) => (element, fromValue, toValue, progress) => (0, import_math.lerp)(fromValue != null ? fromValue : defaultValue, toValue != null ? toValue : defaultValue, progress);
|
|
72
|
+
var scaleRenderStrategy = generateLerpRenderStrategy(1);
|
|
73
|
+
var degreesRenderStrategy = generateLerpRenderStrategy(0);
|
|
74
|
+
var transformRenderStrategies = {
|
|
75
|
+
x: widthBasedTranslateRenderStrategy,
|
|
76
|
+
y: heightBasedTranslateRenderStrategy,
|
|
77
|
+
z: widthBasedTranslateRenderStrategy,
|
|
78
|
+
scale: scaleRenderStrategy,
|
|
79
|
+
scaleX: scaleRenderStrategy,
|
|
80
|
+
scaleY: scaleRenderStrategy,
|
|
81
|
+
scaleZ: scaleRenderStrategy,
|
|
82
|
+
skew: degreesRenderStrategy,
|
|
83
|
+
skewX: degreesRenderStrategy,
|
|
84
|
+
skewY: degreesRenderStrategy,
|
|
85
|
+
rotate: degreesRenderStrategy,
|
|
86
|
+
rotateX: degreesRenderStrategy,
|
|
87
|
+
rotateY: degreesRenderStrategy,
|
|
88
|
+
rotateZ: degreesRenderStrategy
|
|
89
|
+
};
|
|
90
|
+
function render(element, from, to, progress) {
|
|
91
|
+
const stepProgress = to.easing((0, import_math.map)(progress, from.offset, to.offset, 0, 1));
|
|
92
|
+
import_scheduler.domScheduler.read(function renderRead() {
|
|
93
|
+
var _a, _b;
|
|
94
|
+
let opacity = false;
|
|
95
|
+
if ((0, import_isDefined.default)(from.opacity) || (0, import_isDefined.default)(to.opacity)) {
|
|
96
|
+
opacity = (0, import_math.map)(stepProgress, 0, 1, (_a = from.opacity) != null ? _a : 1, (_b = to.opacity) != null ? _b : 1);
|
|
97
|
+
} else if (element.style.opacity) {
|
|
98
|
+
opacity = "";
|
|
99
|
+
}
|
|
100
|
+
let transformOrigin = false;
|
|
101
|
+
if ((0, import_isDefined.default)(to.transformOrigin)) {
|
|
102
|
+
transformOrigin = to.transformOrigin;
|
|
103
|
+
} else if (element.style.transformOrigin) {
|
|
104
|
+
transformOrigin = "";
|
|
105
|
+
}
|
|
106
|
+
const props = Object.fromEntries(import_transform.TRANSFORM_PROPS.filter((name) => (0, import_isDefined.default)(from[name]) || (0, import_isDefined.default)(to[name])).map((name) => {
|
|
107
|
+
return [name, transformRenderStrategies[name](element, from[name], to[name], stepProgress)];
|
|
108
|
+
}));
|
|
109
|
+
import_scheduler.domScheduler.write(function renderWrite() {
|
|
110
|
+
if (opacity !== false) {
|
|
111
|
+
element.style.opacity = opacity;
|
|
112
|
+
}
|
|
113
|
+
if (transformOrigin !== false) {
|
|
114
|
+
element.style.transformOrigin = transformOrigin;
|
|
115
|
+
}
|
|
116
|
+
(0, import_transform.default)(element, props);
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
function animate(element, keyframes, options = {}) {
|
|
121
|
+
var _a;
|
|
122
|
+
let progressValue = 0;
|
|
123
|
+
let easedProgress = 0;
|
|
124
|
+
if (!running.has(element)) {
|
|
125
|
+
running.set(element, /* @__PURE__ */ new Map());
|
|
126
|
+
}
|
|
127
|
+
const ease = normalizeEase(options.easing);
|
|
128
|
+
let duration = (_a = options.duration) != null ? _a : 1;
|
|
129
|
+
duration *= 1e3;
|
|
130
|
+
let startTime = performance.now();
|
|
131
|
+
let endTime = startTime + duration;
|
|
132
|
+
const key = `animate-${id}`;
|
|
133
|
+
id += 1;
|
|
134
|
+
const { onProgress = noop, onFinish = noop } = options;
|
|
135
|
+
let isRunning = false;
|
|
136
|
+
const keyframesCount = keyframes.length - 1;
|
|
137
|
+
const normalizedKeyframes = keyframes.map((keyframe, index) => {
|
|
138
|
+
var _a2;
|
|
139
|
+
return {
|
|
140
|
+
...keyframe,
|
|
141
|
+
offset: (_a2 = keyframe.offset) != null ? _a2 : index / keyframesCount,
|
|
142
|
+
easing: normalizeEase(keyframe.easing)
|
|
143
|
+
};
|
|
144
|
+
});
|
|
145
|
+
function pause() {
|
|
146
|
+
isRunning = false;
|
|
147
|
+
raf.remove(key);
|
|
148
|
+
}
|
|
149
|
+
function progress(newProgress) {
|
|
150
|
+
if (typeof newProgress === "undefined") {
|
|
151
|
+
return progressValue;
|
|
152
|
+
}
|
|
153
|
+
progressValue = newProgress;
|
|
154
|
+
if (Math.abs(1 - progressValue) < PROGRESS_PRECISION) {
|
|
155
|
+
progressValue = 1;
|
|
156
|
+
pause();
|
|
157
|
+
import_scheduler.domScheduler.afterWrite(() => onFinish(progressValue, easedProgress));
|
|
158
|
+
}
|
|
159
|
+
easedProgress = ease(progressValue);
|
|
160
|
+
let toIndex = 0;
|
|
161
|
+
while (normalizedKeyframes[toIndex] && normalizedKeyframes[toIndex].offset <= easedProgress && normalizedKeyframes[toIndex].offset !== 1) {
|
|
162
|
+
toIndex += 1;
|
|
163
|
+
}
|
|
164
|
+
render(element, normalizedKeyframes[toIndex - 1], normalizedKeyframes[toIndex], easedProgress);
|
|
165
|
+
onProgress(progressValue, easedProgress);
|
|
166
|
+
return progressValue;
|
|
167
|
+
}
|
|
168
|
+
function tick(props) {
|
|
169
|
+
if (!isRunning) {
|
|
170
|
+
raf.remove(key);
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
progress((0, import_math.clamp01)((0, import_math.map)(props.time, startTime, endTime, 0, 1)));
|
|
174
|
+
}
|
|
175
|
+
function start() {
|
|
176
|
+
const runningKeys = running.get(element);
|
|
177
|
+
runningKeys.forEach((runningPause, runningKey) => {
|
|
178
|
+
runningPause();
|
|
179
|
+
runningKeys.delete(runningKey);
|
|
180
|
+
});
|
|
181
|
+
runningKeys.set(key, pause);
|
|
182
|
+
running.set(element, runningKeys);
|
|
183
|
+
startTime = performance.now();
|
|
184
|
+
endTime = startTime + duration;
|
|
185
|
+
progressValue = 0;
|
|
186
|
+
easedProgress = 0;
|
|
187
|
+
isRunning = true;
|
|
188
|
+
raf.add(key, tick);
|
|
189
|
+
}
|
|
190
|
+
function play() {
|
|
191
|
+
if (isRunning) {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
startTime = performance.now() - (0, import_math.lerp)(0, duration, progressValue);
|
|
195
|
+
endTime = startTime + duration;
|
|
196
|
+
isRunning = true;
|
|
197
|
+
raf.add(key, tick);
|
|
198
|
+
}
|
|
199
|
+
return {
|
|
200
|
+
start,
|
|
201
|
+
finish: () => progress(1),
|
|
202
|
+
pause,
|
|
203
|
+
play,
|
|
204
|
+
progress
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
if (module.exports.default) module.exports = module.exports.default;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {import('./transform.js').TransformProps} TransformProps
|
|
3
|
+
* @typedef {import('../math/ease.js').EasingFunction} EasingFn
|
|
4
|
+
* @typedef {[number, number, number, number]} BezierCurve
|
|
5
|
+
* @typedef {{
|
|
6
|
+
* duration?: number;
|
|
7
|
+
* easing?: EasingFn|BezierCurve;
|
|
8
|
+
* onProgress?: (progress: number, easedProgress: number) => void;
|
|
9
|
+
* onFinish?: (progress: number, easedProgress: number) => void;
|
|
10
|
+
* }} Options
|
|
11
|
+
* @typedef {TransformProps & {
|
|
12
|
+
* opacity?: number;
|
|
13
|
+
* transformOrigin?: string;
|
|
14
|
+
* easing?: EasingFn|BezierCurve;
|
|
15
|
+
* offset?: number;
|
|
16
|
+
* }} Keyframe
|
|
17
|
+
* @typedef {Keyframe & {
|
|
18
|
+
* easing: EasingFn;
|
|
19
|
+
* offset: number;
|
|
20
|
+
* }} NormalizedKeyframe
|
|
21
|
+
* @typedef {{
|
|
22
|
+
* start: () => void;
|
|
23
|
+
* pause: () => void;
|
|
24
|
+
* play: () => void;
|
|
25
|
+
* finish: () => void;
|
|
26
|
+
* progress: (value: number?) => number
|
|
27
|
+
* }} Animate
|
|
28
|
+
*/
|
|
29
|
+
/**
|
|
30
|
+
* Animate an element.
|
|
31
|
+
* @param {HTMLElement} element
|
|
32
|
+
* @param {Keyframe[]} keyframes
|
|
33
|
+
* @param {Options} options
|
|
34
|
+
* @returns {Animate}
|
|
35
|
+
*/
|
|
36
|
+
export function animate(element: HTMLElement, keyframes: Keyframe[], options?: Options): Animate;
|
|
37
|
+
export type TransformProps = import('./transform.js').TransformProps;
|
|
38
|
+
export type EasingFn = import('../math/ease.js').EasingFunction;
|
|
39
|
+
export type BezierCurve = [number, number, number, number];
|
|
40
|
+
export type Options = Options;
|
|
41
|
+
export type Keyframe = TransformProps & {
|
|
42
|
+
opacity?: number;
|
|
43
|
+
transformOrigin?: string;
|
|
44
|
+
easing?: EasingFn | [number, number, number, number];
|
|
45
|
+
offset?: number;
|
|
46
|
+
};
|
|
47
|
+
export type NormalizedKeyframe = Keyframe & {
|
|
48
|
+
easing: EasingFn;
|
|
49
|
+
offset: number;
|
|
50
|
+
};
|
|
51
|
+
export type Animate = {
|
|
52
|
+
start: () => void;
|
|
53
|
+
pause: () => void;
|
|
54
|
+
play: () => void;
|
|
55
|
+
finish: () => void;
|
|
56
|
+
progress: (value: number | null) => number;
|
|
57
|
+
};
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { cubicBezier } from "@motionone/easing";
|
|
2
|
+
import { lerp, map, clamp01 } from "../math/index.js";
|
|
3
|
+
import isDefined from "../isDefined.js";
|
|
4
|
+
import transform, { TRANSFORM_PROPS } from "./transform.js";
|
|
5
|
+
import useRaf from "../../services/raf.js";
|
|
6
|
+
import { domScheduler as scheduler } from "../scheduler.js";
|
|
7
|
+
let id = 0;
|
|
8
|
+
const running = /* @__PURE__ */ new WeakMap();
|
|
9
|
+
const raf = useRaf();
|
|
10
|
+
const noop = () => {
|
|
11
|
+
};
|
|
12
|
+
const PROGRESS_PRECISION = 1e-4;
|
|
13
|
+
const CSSUnitConverter = {
|
|
14
|
+
"%": (value, getSizeRef) => value * getSizeRef() / 100,
|
|
15
|
+
vh: (value) => value * window.innerHeight / 100,
|
|
16
|
+
vw: (value) => value * window.innerWidth / 100,
|
|
17
|
+
vmin: (value) => value * Math.min(window.innerWidth, window.innerHeight) / 100,
|
|
18
|
+
vmax: (value) => value * Math.max(window.innerWidth, window.innerHeight) / 100
|
|
19
|
+
};
|
|
20
|
+
function getAnimationStepValue(val, getSizeRef) {
|
|
21
|
+
if (typeof val === "number") {
|
|
22
|
+
return val;
|
|
23
|
+
}
|
|
24
|
+
if (!val[1] || !CSSUnitConverter[val[1]]) {
|
|
25
|
+
return val[0];
|
|
26
|
+
}
|
|
27
|
+
return CSSUnitConverter[val[1]](val[0], getSizeRef);
|
|
28
|
+
}
|
|
29
|
+
function linear(value) {
|
|
30
|
+
return value;
|
|
31
|
+
}
|
|
32
|
+
function normalizeEase(ease) {
|
|
33
|
+
if (!isDefined(ease)) {
|
|
34
|
+
return linear;
|
|
35
|
+
}
|
|
36
|
+
if (Array.isArray(ease)) {
|
|
37
|
+
return cubicBezier(...ease);
|
|
38
|
+
}
|
|
39
|
+
return ease;
|
|
40
|
+
}
|
|
41
|
+
const generateTranslateRenderStrategy = (sizeRef) => (element, fromValue, toValue, progress) => lerp(getAnimationStepValue(fromValue != null ? fromValue : 0, () => element[sizeRef]), getAnimationStepValue(toValue != null ? toValue : 0, () => element[sizeRef]), progress);
|
|
42
|
+
const widthBasedTranslateRenderStrategy = generateTranslateRenderStrategy("offsetWidth");
|
|
43
|
+
const heightBasedTranslateRenderStrategy = generateTranslateRenderStrategy("offsetHeight");
|
|
44
|
+
const generateLerpRenderStrategy = (defaultValue) => (element, fromValue, toValue, progress) => lerp(fromValue != null ? fromValue : defaultValue, toValue != null ? toValue : defaultValue, progress);
|
|
45
|
+
const scaleRenderStrategy = generateLerpRenderStrategy(1);
|
|
46
|
+
const degreesRenderStrategy = generateLerpRenderStrategy(0);
|
|
47
|
+
const transformRenderStrategies = {
|
|
48
|
+
x: widthBasedTranslateRenderStrategy,
|
|
49
|
+
y: heightBasedTranslateRenderStrategy,
|
|
50
|
+
z: widthBasedTranslateRenderStrategy,
|
|
51
|
+
scale: scaleRenderStrategy,
|
|
52
|
+
scaleX: scaleRenderStrategy,
|
|
53
|
+
scaleY: scaleRenderStrategy,
|
|
54
|
+
scaleZ: scaleRenderStrategy,
|
|
55
|
+
skew: degreesRenderStrategy,
|
|
56
|
+
skewX: degreesRenderStrategy,
|
|
57
|
+
skewY: degreesRenderStrategy,
|
|
58
|
+
rotate: degreesRenderStrategy,
|
|
59
|
+
rotateX: degreesRenderStrategy,
|
|
60
|
+
rotateY: degreesRenderStrategy,
|
|
61
|
+
rotateZ: degreesRenderStrategy
|
|
62
|
+
};
|
|
63
|
+
function render(element, from, to, progress) {
|
|
64
|
+
const stepProgress = to.easing(map(progress, from.offset, to.offset, 0, 1));
|
|
65
|
+
scheduler.read(function renderRead() {
|
|
66
|
+
var _a, _b;
|
|
67
|
+
let opacity = false;
|
|
68
|
+
if (isDefined(from.opacity) || isDefined(to.opacity)) {
|
|
69
|
+
opacity = map(stepProgress, 0, 1, (_a = from.opacity) != null ? _a : 1, (_b = to.opacity) != null ? _b : 1);
|
|
70
|
+
} else if (element.style.opacity) {
|
|
71
|
+
opacity = "";
|
|
72
|
+
}
|
|
73
|
+
let transformOrigin = false;
|
|
74
|
+
if (isDefined(to.transformOrigin)) {
|
|
75
|
+
transformOrigin = to.transformOrigin;
|
|
76
|
+
} else if (element.style.transformOrigin) {
|
|
77
|
+
transformOrigin = "";
|
|
78
|
+
}
|
|
79
|
+
const props = Object.fromEntries(TRANSFORM_PROPS.filter((name) => isDefined(from[name]) || isDefined(to[name])).map((name) => {
|
|
80
|
+
return [name, transformRenderStrategies[name](element, from[name], to[name], stepProgress)];
|
|
81
|
+
}));
|
|
82
|
+
scheduler.write(function renderWrite() {
|
|
83
|
+
if (opacity !== false) {
|
|
84
|
+
element.style.opacity = opacity;
|
|
85
|
+
}
|
|
86
|
+
if (transformOrigin !== false) {
|
|
87
|
+
element.style.transformOrigin = transformOrigin;
|
|
88
|
+
}
|
|
89
|
+
transform(element, props);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
function animate(element, keyframes, options = {}) {
|
|
94
|
+
var _a;
|
|
95
|
+
let progressValue = 0;
|
|
96
|
+
let easedProgress = 0;
|
|
97
|
+
if (!running.has(element)) {
|
|
98
|
+
running.set(element, /* @__PURE__ */ new Map());
|
|
99
|
+
}
|
|
100
|
+
const ease = normalizeEase(options.easing);
|
|
101
|
+
let duration = (_a = options.duration) != null ? _a : 1;
|
|
102
|
+
duration *= 1e3;
|
|
103
|
+
let startTime = performance.now();
|
|
104
|
+
let endTime = startTime + duration;
|
|
105
|
+
const key = `animate-${id}`;
|
|
106
|
+
id += 1;
|
|
107
|
+
const { onProgress = noop, onFinish = noop } = options;
|
|
108
|
+
let isRunning = false;
|
|
109
|
+
const keyframesCount = keyframes.length - 1;
|
|
110
|
+
const normalizedKeyframes = keyframes.map((keyframe, index) => {
|
|
111
|
+
var _a2;
|
|
112
|
+
return {
|
|
113
|
+
...keyframe,
|
|
114
|
+
offset: (_a2 = keyframe.offset) != null ? _a2 : index / keyframesCount,
|
|
115
|
+
easing: normalizeEase(keyframe.easing)
|
|
116
|
+
};
|
|
117
|
+
});
|
|
118
|
+
function pause() {
|
|
119
|
+
isRunning = false;
|
|
120
|
+
raf.remove(key);
|
|
121
|
+
}
|
|
122
|
+
function progress(newProgress) {
|
|
123
|
+
if (typeof newProgress === "undefined") {
|
|
124
|
+
return progressValue;
|
|
125
|
+
}
|
|
126
|
+
progressValue = newProgress;
|
|
127
|
+
if (Math.abs(1 - progressValue) < PROGRESS_PRECISION) {
|
|
128
|
+
progressValue = 1;
|
|
129
|
+
pause();
|
|
130
|
+
scheduler.afterWrite(() => onFinish(progressValue, easedProgress));
|
|
131
|
+
}
|
|
132
|
+
easedProgress = ease(progressValue);
|
|
133
|
+
let toIndex = 0;
|
|
134
|
+
while (normalizedKeyframes[toIndex] && normalizedKeyframes[toIndex].offset <= easedProgress && normalizedKeyframes[toIndex].offset !== 1) {
|
|
135
|
+
toIndex += 1;
|
|
136
|
+
}
|
|
137
|
+
render(element, normalizedKeyframes[toIndex - 1], normalizedKeyframes[toIndex], easedProgress);
|
|
138
|
+
onProgress(progressValue, easedProgress);
|
|
139
|
+
return progressValue;
|
|
140
|
+
}
|
|
141
|
+
function tick(props) {
|
|
142
|
+
if (!isRunning) {
|
|
143
|
+
raf.remove(key);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
progress(clamp01(map(props.time, startTime, endTime, 0, 1)));
|
|
147
|
+
}
|
|
148
|
+
function start() {
|
|
149
|
+
const runningKeys = running.get(element);
|
|
150
|
+
runningKeys.forEach((runningPause, runningKey) => {
|
|
151
|
+
runningPause();
|
|
152
|
+
runningKeys.delete(runningKey);
|
|
153
|
+
});
|
|
154
|
+
runningKeys.set(key, pause);
|
|
155
|
+
running.set(element, runningKeys);
|
|
156
|
+
startTime = performance.now();
|
|
157
|
+
endTime = startTime + duration;
|
|
158
|
+
progressValue = 0;
|
|
159
|
+
easedProgress = 0;
|
|
160
|
+
isRunning = true;
|
|
161
|
+
raf.add(key, tick);
|
|
162
|
+
}
|
|
163
|
+
function play() {
|
|
164
|
+
if (isRunning) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
startTime = performance.now() - lerp(0, duration, progressValue);
|
|
168
|
+
endTime = startTime + duration;
|
|
169
|
+
isRunning = true;
|
|
170
|
+
raf.add(key, tick);
|
|
171
|
+
}
|
|
172
|
+
return {
|
|
173
|
+
start,
|
|
174
|
+
finish: () => progress(1),
|
|
175
|
+
pause,
|
|
176
|
+
play,
|
|
177
|
+
progress
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
export {
|
|
181
|
+
animate
|
|
182
|
+
};
|