@pixerate/editor 0.27.0 → 0.28.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.
- package/README.md +25 -2
- package/dist/animation/index.cjs +62 -0
- package/dist/animation/index.cjs.map +1 -0
- package/dist/animation/index.d.cts +296 -0
- package/dist/animation/index.d.ts +296 -0
- package/dist/animation/index.js +62 -0
- package/dist/animation/index.js.map +1 -0
- package/dist/canvas/index.cjs +177 -743
- package/dist/canvas/index.cjs.map +1 -1
- package/dist/canvas/index.d.cts +3 -288
- package/dist/canvas/index.d.ts +3 -288
- package/dist/canvas/index.js +49 -615
- package/dist/canvas/index.js.map +1 -1
- package/dist/{chunk-JT7AXQTE.js → chunk-3RPOW4CS.js} +7 -7
- package/dist/chunk-A6PHCAGX.cjs +87 -0
- package/dist/chunk-A6PHCAGX.cjs.map +1 -0
- package/dist/{chunk-HRMEDT2L.js → chunk-D6AVOTSD.js} +6 -85
- package/dist/chunk-D6AVOTSD.js.map +1 -0
- package/dist/{chunk-4BVP64JJ.cjs → chunk-K2UYKJ6M.cjs} +24 -103
- package/dist/chunk-K2UYKJ6M.cjs.map +1 -0
- package/dist/{chunk-6IO7WUSU.js → chunk-MXZJ4PKN.js} +14 -14
- package/dist/{chunk-AGR7EVRW.cjs → chunk-OYEFRO3D.cjs} +6 -6
- package/dist/{chunk-AGR7EVRW.cjs.map → chunk-OYEFRO3D.cjs.map} +1 -1
- package/dist/chunk-PWJARCI4.js +637 -0
- package/dist/chunk-PWJARCI4.js.map +1 -0
- package/dist/chunk-TGD52FEZ.js +87 -0
- package/dist/chunk-TGD52FEZ.js.map +1 -0
- package/dist/chunk-TTYCN6ZH.cjs +637 -0
- package/dist/chunk-TTYCN6ZH.cjs.map +1 -0
- package/dist/{chunk-YK5TATOF.cjs → chunk-U7VGDSNY.cjs} +3 -3
- package/dist/{chunk-YK5TATOF.cjs.map → chunk-U7VGDSNY.cjs.map} +1 -1
- package/dist/extensions/index.cjs +7 -7
- package/dist/extensions/index.cjs.map +1 -1
- package/dist/extensions/index.js +12 -12
- package/dist/generation/index.cjs +3 -3
- package/dist/generation/index.cjs.map +1 -1
- package/dist/generation/index.js +3 -3
- package/dist/index.cjs +20 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +103 -103
- package/dist/spreadsheet/index.cjs +4 -4
- package/dist/spreadsheet/index.cjs.map +1 -1
- package/dist/spreadsheet/index.js +8 -8
- package/dist/tokens/index.cjs +4 -2
- package/dist/tokens/index.cjs.map +1 -1
- package/dist/tokens/index.js +6 -4
- package/package.json +6 -1
- package/dist/chunk-4BVP64JJ.cjs.map +0 -1
- package/dist/chunk-HRMEDT2L.js.map +0 -1
- /package/dist/{chunk-JT7AXQTE.js.map → chunk-3RPOW4CS.js.map} +0 -0
- /package/dist/{chunk-6IO7WUSU.js.map → chunk-MXZJ4PKN.js.map} +0 -0
package/dist/canvas/index.js
CHANGED
|
@@ -1,13 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
TokenError,
|
|
3
|
-
getTokenCollection,
|
|
4
|
-
getTokenVariable,
|
|
5
|
-
hexToRgba,
|
|
6
|
-
isTokenInScope,
|
|
7
|
-
normalizeTokenColor,
|
|
8
|
-
resolveToken,
|
|
9
|
-
rgbaToHex
|
|
10
|
-
} from "../chunk-HRMEDT2L.js";
|
|
11
1
|
import {
|
|
12
2
|
DEFAULT_NODE_HEIGHT,
|
|
13
3
|
DEFAULT_NODE_WIDTH,
|
|
@@ -27,79 +17,46 @@ import {
|
|
|
27
17
|
DEFAULT_ARRANGE_SHORTCUTS,
|
|
28
18
|
matchArrangeShortcut
|
|
29
19
|
} from "../chunk-7DWMJCAT.js";
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
/** Whether any frames or sleep timers are currently pending. */
|
|
71
|
-
get pending() {
|
|
72
|
-
return this.frames.length > 0 || this.sleepers.length > 0;
|
|
73
|
-
}
|
|
74
|
-
/** Advances time by `ms`, resolving due sleep timers in order, followed by queued frames. */
|
|
75
|
-
async advance(ms) {
|
|
76
|
-
const end = this.time + Math.max(0, ms);
|
|
77
|
-
await settle();
|
|
78
|
-
while (true) {
|
|
79
|
-
let next;
|
|
80
|
-
for (const s of this.sleepers) {
|
|
81
|
-
if (s.at <= end && (!next || s.at < next.at || s.at === next.at && s.seq < next.seq)) {
|
|
82
|
-
next = s;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
if (!next) break;
|
|
86
|
-
this.sleepers.splice(this.sleepers.indexOf(next), 1);
|
|
87
|
-
this.time = Math.max(this.time, next.at);
|
|
88
|
-
next.resolve();
|
|
89
|
-
await settle();
|
|
90
|
-
}
|
|
91
|
-
this.time = end;
|
|
92
|
-
const dueFrames = this.frames.splice(0, this.frames.length);
|
|
93
|
-
for (const resolveFrame of dueFrames) {
|
|
94
|
-
resolveFrame();
|
|
95
|
-
}
|
|
96
|
-
await settle();
|
|
97
|
-
}
|
|
98
|
-
/** Convenience method to advance by 1 frame at a given fps (default: 60fps = 16.67ms). */
|
|
99
|
-
async tick(fps = 60) {
|
|
100
|
-
await this.advance(Math.round(1e3 / fps));
|
|
101
|
-
}
|
|
102
|
-
};
|
|
20
|
+
import {
|
|
21
|
+
TokenError,
|
|
22
|
+
getTokenCollection,
|
|
23
|
+
getTokenVariable,
|
|
24
|
+
isTokenInScope,
|
|
25
|
+
resolveToken
|
|
26
|
+
} from "../chunk-D6AVOTSD.js";
|
|
27
|
+
import {
|
|
28
|
+
ANIMATION_EASING_LABELS,
|
|
29
|
+
ANIMATION_EASING_PRESETS,
|
|
30
|
+
ANIMATION_TIME_EPSILON,
|
|
31
|
+
AnimationPlayer,
|
|
32
|
+
CUBIC_BEZIER_PRESETS,
|
|
33
|
+
ManualClock,
|
|
34
|
+
createAnimationPlayer,
|
|
35
|
+
cubicBezierAt,
|
|
36
|
+
easingFromInfluence,
|
|
37
|
+
easingLabel,
|
|
38
|
+
easingToCss,
|
|
39
|
+
evaluateEasing,
|
|
40
|
+
evaluateTrack,
|
|
41
|
+
formatOklab,
|
|
42
|
+
interpolateAnimationValue,
|
|
43
|
+
isAnimationEasing,
|
|
44
|
+
isAnimationKeyframe,
|
|
45
|
+
mixColorsOklab,
|
|
46
|
+
normalizeKeyframes,
|
|
47
|
+
oklabToRgb,
|
|
48
|
+
pageHidden,
|
|
49
|
+
parseCssEasing,
|
|
50
|
+
parseOklab,
|
|
51
|
+
realClock,
|
|
52
|
+
resolveEasing,
|
|
53
|
+
rgbToOklab,
|
|
54
|
+
springAt,
|
|
55
|
+
wrapAnimationTime
|
|
56
|
+
} from "../chunk-PWJARCI4.js";
|
|
57
|
+
import {
|
|
58
|
+
normalizeTokenColor
|
|
59
|
+
} from "../chunk-TGD52FEZ.js";
|
|
103
60
|
|
|
104
61
|
// src/canvas/trajectory.ts
|
|
105
62
|
var defaultEasing = (t) => --t * t * t + 1;
|
|
@@ -2277,7 +2234,7 @@ function fitSingleFrom(pts, u, t0, t1) {
|
|
|
2277
2234
|
let best = generate(pts, u, t0, t1);
|
|
2278
2235
|
let [bestErr, bestSplit] = maxError(pts, best, u);
|
|
2279
2236
|
const params = u.slice();
|
|
2280
|
-
for (let
|
|
2237
|
+
for (let round2 = 0; round2 < MAX_REPARAM; round2++) {
|
|
2281
2238
|
for (let i = 0; i < params.length; i++) params[i] = newton(best, pts[i], params[i]);
|
|
2282
2239
|
const c = generate(pts, params, t0, t1);
|
|
2283
2240
|
const [e, s] = maxError(pts, c, params);
|
|
@@ -7843,244 +7800,8 @@ function pruneCanvasTokenModes(nodes, state) {
|
|
|
7843
7800
|
return changed ? out : nodes;
|
|
7844
7801
|
}
|
|
7845
7802
|
|
|
7846
|
-
// src/canvas/animation/easing.ts
|
|
7847
|
-
var ANIMATION_EASING_PRESETS = [
|
|
7848
|
-
"linear",
|
|
7849
|
-
"ease",
|
|
7850
|
-
"ease-in",
|
|
7851
|
-
"ease-out",
|
|
7852
|
-
"ease-in-out",
|
|
7853
|
-
"ease-in-back",
|
|
7854
|
-
"ease-out-back",
|
|
7855
|
-
"spring",
|
|
7856
|
-
"hold"
|
|
7857
|
-
];
|
|
7858
|
-
var ANIMATION_EASING_LABELS = {
|
|
7859
|
-
linear: "Linear",
|
|
7860
|
-
hold: "Hold",
|
|
7861
|
-
ease: "Ease",
|
|
7862
|
-
"ease-in": "Ease in",
|
|
7863
|
-
"ease-out": "Ease out",
|
|
7864
|
-
"ease-in-out": "Ease in-out",
|
|
7865
|
-
"ease-in-back": "Back in",
|
|
7866
|
-
"ease-out-back": "Back out",
|
|
7867
|
-
spring: "Spring"
|
|
7868
|
-
};
|
|
7869
|
-
var CUBIC_BEZIER_PRESETS = {
|
|
7870
|
-
linear: [0, 0, 1, 1],
|
|
7871
|
-
ease: [0.25, 0.1, 0.25, 1],
|
|
7872
|
-
"ease-in": [0.42, 0, 1, 1],
|
|
7873
|
-
"ease-out": [0, 0, 0.58, 1],
|
|
7874
|
-
"ease-in-out": [0.42, 0, 0.58, 1],
|
|
7875
|
-
"ease-in-back": [0.36, 0, 0.66, -0.56],
|
|
7876
|
-
"ease-out-back": [0.34, 1.56, 0.64, 1]
|
|
7877
|
-
};
|
|
7878
|
-
var DEFAULT_SPRING = { stiffness: 170, damping: 26, mass: 1, velocity: 0 };
|
|
7879
|
-
var clamp = (v, lo, hi) => Math.min(hi, Math.max(lo, v));
|
|
7880
|
-
var finite2 = (v, fallback) => typeof v === "number" && Number.isFinite(v) ? v : fallback;
|
|
7881
|
-
function cubicBezierAt(x1, y1, x2, y2, x) {
|
|
7882
|
-
if (x <= 0) return 0;
|
|
7883
|
-
if (x >= 1) return 1;
|
|
7884
|
-
x1 = clamp(x1, 0, 1);
|
|
7885
|
-
x2 = clamp(x2, 0, 1);
|
|
7886
|
-
const bx = (s2) => 3 * (1 - s2) * (1 - s2) * s2 * x1 + 3 * (1 - s2) * s2 * s2 * x2 + s2 * s2 * s2;
|
|
7887
|
-
const by = (s2) => 3 * (1 - s2) * (1 - s2) * s2 * y1 + 3 * (1 - s2) * s2 * s2 * y2 + s2 * s2 * s2;
|
|
7888
|
-
const dbx = (s2) => 3 * (1 - s2) * (1 - s2) * x1 + 6 * (1 - s2) * s2 * (x2 - x1) + 3 * s2 * s2 * (1 - x2);
|
|
7889
|
-
let s = x;
|
|
7890
|
-
for (let i = 0; i < 8; i++) {
|
|
7891
|
-
const d = dbx(s);
|
|
7892
|
-
if (Math.abs(d) < 1e-9) break;
|
|
7893
|
-
const next = s - (bx(s) - x) / d;
|
|
7894
|
-
if (!(next >= 0 && next <= 1)) break;
|
|
7895
|
-
s = next;
|
|
7896
|
-
}
|
|
7897
|
-
if (Math.abs(bx(s) - x) > 1e-7) {
|
|
7898
|
-
let lo = 0;
|
|
7899
|
-
let hi = 1;
|
|
7900
|
-
for (let i = 0; i < 60; i++) {
|
|
7901
|
-
s = (lo + hi) / 2;
|
|
7902
|
-
if (bx(s) < x) lo = s;
|
|
7903
|
-
else hi = s;
|
|
7904
|
-
}
|
|
7905
|
-
}
|
|
7906
|
-
return by(s);
|
|
7907
|
-
}
|
|
7908
|
-
function springAt(spring, seconds) {
|
|
7909
|
-
const stiffness = Math.max(1e-6, finite2(spring.stiffness, DEFAULT_SPRING.stiffness));
|
|
7910
|
-
const damping = Math.max(0, finite2(spring.damping, DEFAULT_SPRING.damping));
|
|
7911
|
-
const mass = Math.max(1e-6, finite2(spring.mass, DEFAULT_SPRING.mass));
|
|
7912
|
-
const v0 = -finite2(spring.velocity, DEFAULT_SPRING.velocity);
|
|
7913
|
-
const t = Math.max(0, seconds);
|
|
7914
|
-
const w0 = Math.sqrt(stiffness / mass);
|
|
7915
|
-
const zeta = damping / (2 * Math.sqrt(stiffness * mass));
|
|
7916
|
-
let x;
|
|
7917
|
-
if (zeta < 1 - 1e-6) {
|
|
7918
|
-
const wd = w0 * Math.sqrt(1 - zeta * zeta);
|
|
7919
|
-
x = Math.exp(-zeta * w0 * t) * (Math.cos(wd * t) + (zeta * w0 + v0) / wd * Math.sin(wd * t));
|
|
7920
|
-
} else if (zeta <= 1 + 1e-6) {
|
|
7921
|
-
x = Math.exp(-w0 * t) * (1 + (w0 + v0) * t);
|
|
7922
|
-
} else {
|
|
7923
|
-
const r = Math.sqrt(zeta * zeta - 1);
|
|
7924
|
-
const s1 = -w0 * (zeta - r);
|
|
7925
|
-
const s2 = -w0 * (zeta + r);
|
|
7926
|
-
const c2 = (v0 - s1) / (s2 - s1);
|
|
7927
|
-
const c1 = 1 - c2;
|
|
7928
|
-
x = c1 * Math.exp(s1 * t) + c2 * Math.exp(s2 * t);
|
|
7929
|
-
}
|
|
7930
|
-
return 1 - x;
|
|
7931
|
-
}
|
|
7932
|
-
function resolveEasing(easing) {
|
|
7933
|
-
if (easing === "hold") return "hold";
|
|
7934
|
-
if (easing === "spring") return { type: "spring", ...DEFAULT_SPRING };
|
|
7935
|
-
if (typeof easing === "string") {
|
|
7936
|
-
const preset = CUBIC_BEZIER_PRESETS[easing];
|
|
7937
|
-
if (preset) return { type: "cubic-bezier", x1: preset[0], y1: preset[1], x2: preset[2], y2: preset[3] };
|
|
7938
|
-
const parsed = parseCssEasing(easing);
|
|
7939
|
-
return parsed ? resolveEasing(parsed) : { type: "cubic-bezier", x1: 0, y1: 0, x2: 1, y2: 1 };
|
|
7940
|
-
}
|
|
7941
|
-
if (easing && typeof easing === "object") {
|
|
7942
|
-
if (easing.type === "spring") {
|
|
7943
|
-
return {
|
|
7944
|
-
type: "spring",
|
|
7945
|
-
stiffness: finite2(easing.stiffness, DEFAULT_SPRING.stiffness),
|
|
7946
|
-
damping: finite2(easing.damping, DEFAULT_SPRING.damping),
|
|
7947
|
-
mass: finite2(easing.mass, DEFAULT_SPRING.mass),
|
|
7948
|
-
velocity: finite2(easing.velocity, DEFAULT_SPRING.velocity)
|
|
7949
|
-
};
|
|
7950
|
-
}
|
|
7951
|
-
if (easing.type === "cubic-bezier") {
|
|
7952
|
-
return {
|
|
7953
|
-
type: "cubic-bezier",
|
|
7954
|
-
x1: clamp(finite2(easing.x1, 0), 0, 1),
|
|
7955
|
-
y1: finite2(easing.y1, 0),
|
|
7956
|
-
x2: clamp(finite2(easing.x2, 1), 0, 1),
|
|
7957
|
-
y2: finite2(easing.y2, 1)
|
|
7958
|
-
};
|
|
7959
|
-
}
|
|
7960
|
-
}
|
|
7961
|
-
return { type: "cubic-bezier", x1: 0, y1: 0, x2: 1, y2: 1 };
|
|
7962
|
-
}
|
|
7963
|
-
function evaluateEasing(easing, u, durationMs = 1e3) {
|
|
7964
|
-
if (!(u > 0)) return 0;
|
|
7965
|
-
if (u >= 1) return 1;
|
|
7966
|
-
const resolved = resolveEasing(easing);
|
|
7967
|
-
if (resolved === "hold") return 0;
|
|
7968
|
-
if (resolved.type === "spring") return springAt(resolved, u * Math.max(0, durationMs) / 1e3);
|
|
7969
|
-
const { x1, y1, x2, y2 } = resolved;
|
|
7970
|
-
if (x1 === y1 && x2 === y2) return u;
|
|
7971
|
-
return cubicBezierAt(x1, y1, x2, y2, u);
|
|
7972
|
-
}
|
|
7973
|
-
function easingFromInfluence(outInfluence = 1 / 3, inInfluence = 1 / 3) {
|
|
7974
|
-
return {
|
|
7975
|
-
type: "cubic-bezier",
|
|
7976
|
-
x1: clamp(outInfluence, 0.01, 1),
|
|
7977
|
-
y1: 0,
|
|
7978
|
-
x2: 1 - clamp(inInfluence, 0.01, 1),
|
|
7979
|
-
y2: 1
|
|
7980
|
-
};
|
|
7981
|
-
}
|
|
7982
|
-
var NUMBER = String.raw`\s*(-?(?:\d+\.?\d*|\.\d+)(?:e[-+]?\d+)?)\s*`;
|
|
7983
|
-
var CUBIC_RE = new RegExp(`^cubic-bezier\\(${NUMBER},${NUMBER},${NUMBER},${NUMBER}\\)$`, "i");
|
|
7984
|
-
function parseCssEasing(text) {
|
|
7985
|
-
const value = text.trim().toLowerCase();
|
|
7986
|
-
if (value.length > 200) return null;
|
|
7987
|
-
if (ANIMATION_EASING_PRESETS.includes(value)) return value;
|
|
7988
|
-
if (value === "step-end" || /^steps\(\s*1\s*(,\s*(end|jump-end)\s*)?\)$/.test(value)) return "hold";
|
|
7989
|
-
const m = CUBIC_RE.exec(value);
|
|
7990
|
-
if (!m) return null;
|
|
7991
|
-
const [x1, y1, x2, y2] = m.slice(1).map(Number);
|
|
7992
|
-
if (![x1, y1, x2, y2].every(Number.isFinite) || x1 < 0 || x1 > 1 || x2 < 0 || x2 > 1) return null;
|
|
7993
|
-
return { type: "cubic-bezier", x1, y1, x2, y2 };
|
|
7994
|
-
}
|
|
7995
|
-
function isAnimationEasing(value) {
|
|
7996
|
-
if (typeof value === "string") return parseCssEasing(value) !== null;
|
|
7997
|
-
if (typeof value !== "object" || value === null) return false;
|
|
7998
|
-
const e = value;
|
|
7999
|
-
if (e.type === "spring") return true;
|
|
8000
|
-
return e.type === "cubic-bezier" && [e.x1, e.y1, e.x2, e.y2].every((v) => typeof v === "number" && Number.isFinite(v));
|
|
8001
|
-
}
|
|
8002
|
-
var round = (v, digits = 4) => {
|
|
8003
|
-
const p = 10 ** digits;
|
|
8004
|
-
return Math.round(v * p) / p;
|
|
8005
|
-
};
|
|
8006
|
-
function easingToCss(easing, durationMs = 1e3, samples = 24) {
|
|
8007
|
-
const resolved = resolveEasing(easing);
|
|
8008
|
-
if (resolved === "hold") return "steps(1, end)";
|
|
8009
|
-
if (resolved.type === "spring") {
|
|
8010
|
-
const n = Math.max(2, Math.floor(samples));
|
|
8011
|
-
const points = [];
|
|
8012
|
-
for (let i = 0; i <= n; i++) points.push(String(round(i === n ? 1 : springAt(resolved, i / n * durationMs / 1e3))));
|
|
8013
|
-
return `linear(${points.join(", ")})`;
|
|
8014
|
-
}
|
|
8015
|
-
const { x1, y1, x2, y2 } = resolved;
|
|
8016
|
-
for (const [name, p] of Object.entries(CUBIC_BEZIER_PRESETS)) {
|
|
8017
|
-
if (["linear", "ease", "ease-in", "ease-out", "ease-in-out"].includes(name) && p[0] === x1 && p[1] === y1 && p[2] === x2 && p[3] === y2) {
|
|
8018
|
-
return name;
|
|
8019
|
-
}
|
|
8020
|
-
}
|
|
8021
|
-
return `cubic-bezier(${round(x1)}, ${round(y1)}, ${round(x2)}, ${round(y2)})`;
|
|
8022
|
-
}
|
|
8023
|
-
function easingLabel(easing) {
|
|
8024
|
-
if (easing === void 0 || easing === null) return ANIMATION_EASING_LABELS.linear;
|
|
8025
|
-
if (typeof easing === "string") return ANIMATION_EASING_LABELS[easing] ?? easing;
|
|
8026
|
-
return easing.type === "spring" ? "Spring" : "Custom";
|
|
8027
|
-
}
|
|
8028
|
-
|
|
8029
|
-
// src/canvas/animation/color.ts
|
|
8030
|
-
var toLinear = (c) => c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;
|
|
8031
|
-
var toGamma = (c) => c <= 31308e-7 ? 12.92 * c : 1.055 * Math.sign(c) * Math.abs(c) ** (1 / 2.4) - 0.055;
|
|
8032
|
-
function rgbToOklab(r, g, b, alpha = 1) {
|
|
8033
|
-
const lr = toLinear(r);
|
|
8034
|
-
const lg = toLinear(g);
|
|
8035
|
-
const lb = toLinear(b);
|
|
8036
|
-
const l = Math.cbrt(0.4122214708 * lr + 0.5363325363 * lg + 0.0514459929 * lb);
|
|
8037
|
-
const m = Math.cbrt(0.2119034982 * lr + 0.6806995451 * lg + 0.1073969566 * lb);
|
|
8038
|
-
const s = Math.cbrt(0.0883024619 * lr + 0.2817188376 * lg + 0.6299787005 * lb);
|
|
8039
|
-
return {
|
|
8040
|
-
l: 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s,
|
|
8041
|
-
a: 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s,
|
|
8042
|
-
b: 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s,
|
|
8043
|
-
alpha
|
|
8044
|
-
};
|
|
8045
|
-
}
|
|
8046
|
-
function oklabToRgb(color) {
|
|
8047
|
-
const l_ = color.l + 0.3963377774 * color.a + 0.2158037573 * color.b;
|
|
8048
|
-
const m_ = color.l - 0.1055613458 * color.a - 0.0638541728 * color.b;
|
|
8049
|
-
const s_ = color.l - 0.0894841775 * color.a - 1.291485548 * color.b;
|
|
8050
|
-
const l = l_ ** 3;
|
|
8051
|
-
const m = m_ ** 3;
|
|
8052
|
-
const s = s_ ** 3;
|
|
8053
|
-
const clamp01 = (v) => Math.min(1, Math.max(0, v));
|
|
8054
|
-
return {
|
|
8055
|
-
r: clamp01(toGamma(4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s)),
|
|
8056
|
-
g: clamp01(toGamma(-1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s)),
|
|
8057
|
-
b: clamp01(toGamma(-0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s)),
|
|
8058
|
-
a: clamp01(color.alpha)
|
|
8059
|
-
};
|
|
8060
|
-
}
|
|
8061
|
-
function parseOklab(input) {
|
|
8062
|
-
const hex = normalizeTokenColor(input);
|
|
8063
|
-
if (hex === null) return null;
|
|
8064
|
-
const c = hexToRgba(hex);
|
|
8065
|
-
return rgbToOklab(c.r, c.g, c.b, c.a);
|
|
8066
|
-
}
|
|
8067
|
-
function formatOklab(color) {
|
|
8068
|
-
const { r, g, b, a } = oklabToRgb(color);
|
|
8069
|
-
return rgbaToHex(r, g, b, a);
|
|
8070
|
-
}
|
|
8071
|
-
function mixColorsOklab(from, to, t) {
|
|
8072
|
-
const a = parseOklab(from);
|
|
8073
|
-
const b = parseOklab(to);
|
|
8074
|
-
if (!a || !b) return null;
|
|
8075
|
-
const alpha = a.alpha + (b.alpha - a.alpha) * t;
|
|
8076
|
-
const premul = (k) => a[k] * a.alpha + (b[k] * b.alpha - a[k] * a.alpha) * t;
|
|
8077
|
-
if (alpha <= 1e-9) return formatOklab({ l: a.l + (b.l - a.l) * t, a: 0, b: 0, alpha: 0 });
|
|
8078
|
-
return formatOklab({ l: premul("l") / alpha, a: premul("a") / alpha, b: premul("b") / alpha, alpha });
|
|
8079
|
-
}
|
|
8080
|
-
|
|
8081
7803
|
// src/canvas/animation/model.ts
|
|
8082
7804
|
var ANIMATION_DATA_KEY = "animation";
|
|
8083
|
-
var ANIMATION_TIME_EPSILON = 1e-6;
|
|
8084
7805
|
var num = (value) => {
|
|
8085
7806
|
if (typeof value === "number") return Number.isFinite(value) ? value : void 0;
|
|
8086
7807
|
if (typeof value === "string") {
|
|
@@ -8221,37 +7942,6 @@ function clampAnimationValue(property, value) {
|
|
|
8221
7942
|
if (property.max !== void 0) v = Math.min(property.max, v);
|
|
8222
7943
|
return v;
|
|
8223
7944
|
}
|
|
8224
|
-
function isValue(value) {
|
|
8225
|
-
return typeof value === "number" && Number.isFinite(value) || typeof value === "string";
|
|
8226
|
-
}
|
|
8227
|
-
function isAnimationKeyframe(value) {
|
|
8228
|
-
if (typeof value !== "object" || value === null) return false;
|
|
8229
|
-
const k = value;
|
|
8230
|
-
return typeof k.time === "number" && Number.isFinite(k.time) && isValue(k.value) && (k.easing === void 0 || isAnimationEasing(k.easing));
|
|
8231
|
-
}
|
|
8232
|
-
var sortedCache = /* @__PURE__ */ new WeakMap();
|
|
8233
|
-
function normalizeKeyframes(keyframes) {
|
|
8234
|
-
if (!Array.isArray(keyframes)) return [];
|
|
8235
|
-
const cached = sortedCache.get(keyframes);
|
|
8236
|
-
if (cached && cached.items.length === keyframes.length && cached.items.every((k, i) => k === keyframes[i])) return cached.out;
|
|
8237
|
-
const indexed = keyframes.map((k, i) => ({ k, i })).filter(({ k }) => isAnimationKeyframe(k)).sort((a, b) => a.k.time - b.k.time || a.i - b.i);
|
|
8238
|
-
const out = [];
|
|
8239
|
-
let lastIndex = -1;
|
|
8240
|
-
for (const { k, i } of indexed) {
|
|
8241
|
-
const prev = out[out.length - 1];
|
|
8242
|
-
if (prev && Math.abs(k.time - prev.time) <= ANIMATION_TIME_EPSILON) {
|
|
8243
|
-
if (i > lastIndex) {
|
|
8244
|
-
out[out.length - 1] = k;
|
|
8245
|
-
lastIndex = i;
|
|
8246
|
-
}
|
|
8247
|
-
continue;
|
|
8248
|
-
}
|
|
8249
|
-
out.push(k);
|
|
8250
|
-
lastIndex = i;
|
|
8251
|
-
}
|
|
8252
|
-
sortedCache.set(keyframes, { items: [...keyframes], out });
|
|
8253
|
-
return out;
|
|
8254
|
-
}
|
|
8255
7945
|
function getNodeAnimation(node) {
|
|
8256
7946
|
const raw = node?.data?.[ANIMATION_DATA_KEY];
|
|
8257
7947
|
if (typeof raw !== "object" || raw === null || typeof raw.tracks !== "object" || raw.tracks === null) return null;
|
|
@@ -8289,45 +7979,6 @@ function withNodeAnimation(node, animation) {
|
|
|
8289
7979
|
|
|
8290
7980
|
// src/canvas/animation/evaluate.ts
|
|
8291
7981
|
var nodesOf = (doc) => Array.isArray(doc) ? doc : doc.nodes;
|
|
8292
|
-
function interpolateAnimationValue(from, to, t, type = "number") {
|
|
8293
|
-
if (typeof from === "number" && typeof to === "number") return from + (to - from) * t;
|
|
8294
|
-
if (t <= 0) return from;
|
|
8295
|
-
if (t >= 1) return to;
|
|
8296
|
-
if (type === "color" || typeof from === "string" && typeof to === "string") {
|
|
8297
|
-
const mixed = mixColorsOklab(from, to, t);
|
|
8298
|
-
if (mixed !== null) return mixed;
|
|
8299
|
-
}
|
|
8300
|
-
return from;
|
|
8301
|
-
}
|
|
8302
|
-
function segmentIndex(keys, time) {
|
|
8303
|
-
let lo = 0;
|
|
8304
|
-
let hi = keys.length - 1;
|
|
8305
|
-
let found = -1;
|
|
8306
|
-
while (lo <= hi) {
|
|
8307
|
-
const mid = lo + hi >> 1;
|
|
8308
|
-
if (keys[mid].time <= time) {
|
|
8309
|
-
found = mid;
|
|
8310
|
-
lo = mid + 1;
|
|
8311
|
-
} else hi = mid - 1;
|
|
8312
|
-
}
|
|
8313
|
-
return found;
|
|
8314
|
-
}
|
|
8315
|
-
function evaluateTrack(track, time, type = "number") {
|
|
8316
|
-
const keyframes = Array.isArray(track) ? track : track?.keyframes;
|
|
8317
|
-
const keys = normalizeKeyframes(keyframes);
|
|
8318
|
-
if (keys.length === 0) return void 0;
|
|
8319
|
-
if (!(time > keys[0].time)) return keys[0].value;
|
|
8320
|
-
const last = keys[keys.length - 1];
|
|
8321
|
-
if (time >= last.time) return last.value;
|
|
8322
|
-
const i = segmentIndex(keys, time);
|
|
8323
|
-
const a = keys[i];
|
|
8324
|
-
const b = keys[i + 1];
|
|
8325
|
-
if (time === a.time) return a.value;
|
|
8326
|
-
const span = b.time - a.time;
|
|
8327
|
-
const u = (time - a.time) / span;
|
|
8328
|
-
if (a.easing === "hold") return a.value;
|
|
8329
|
-
return interpolateAnimationValue(a.value, b.value, evaluateEasing(a.easing, u, span), type);
|
|
8330
|
-
}
|
|
8331
7982
|
function getAnimationDuration(doc) {
|
|
8332
7983
|
let end = 0;
|
|
8333
7984
|
for (const node of nodesOf(doc)) {
|
|
@@ -8341,17 +7992,6 @@ function getAnimationDuration(doc) {
|
|
|
8341
7992
|
}
|
|
8342
7993
|
return end;
|
|
8343
7994
|
}
|
|
8344
|
-
function wrapAnimationTime(time, duration, loop = "none") {
|
|
8345
|
-
if (!Number.isFinite(time)) return 0;
|
|
8346
|
-
if (!(duration > 0)) return 0;
|
|
8347
|
-
if (loop === "loop") return (time % duration + duration) % duration;
|
|
8348
|
-
if (loop === "ping-pong") {
|
|
8349
|
-
const period = duration * 2;
|
|
8350
|
-
const m = (time % period + period) % period;
|
|
8351
|
-
return m <= duration ? m : period - m;
|
|
8352
|
-
}
|
|
8353
|
-
return Math.min(duration, Math.max(0, time));
|
|
8354
|
-
}
|
|
8355
7995
|
function evaluateAnimation(doc, time, options = {}) {
|
|
8356
7996
|
const only = options.ids ? new Set(options.ids) : null;
|
|
8357
7997
|
const out = {};
|
|
@@ -8873,212 +8513,6 @@ function animateNode(nodes, nodeId, options) {
|
|
|
8873
8513
|
return { nodes: draft.commit(), refs };
|
|
8874
8514
|
}
|
|
8875
8515
|
|
|
8876
|
-
// src/canvas/animation/player.ts
|
|
8877
|
-
var AnimationPlayer = class {
|
|
8878
|
-
clock;
|
|
8879
|
-
durationSource;
|
|
8880
|
-
onTime;
|
|
8881
|
-
onEnd;
|
|
8882
|
-
time;
|
|
8883
|
-
playing = false;
|
|
8884
|
-
scrubbing = false;
|
|
8885
|
-
resumeAfterScrub = false;
|
|
8886
|
-
loop;
|
|
8887
|
-
rate;
|
|
8888
|
-
/** Unwrapped time at `anchorAt` (keeps the ping-pong direction across frames). */
|
|
8889
|
-
anchorRaw = 0;
|
|
8890
|
-
anchorAt = 0;
|
|
8891
|
-
generation = 0;
|
|
8892
|
-
cached;
|
|
8893
|
-
listeners = /* @__PURE__ */ new Set();
|
|
8894
|
-
constructor(options = {}) {
|
|
8895
|
-
this.clock = options.clock ?? realClock;
|
|
8896
|
-
this.durationSource = options.duration ?? 1e3;
|
|
8897
|
-
this.loop = options.loop ?? "none";
|
|
8898
|
-
this.rate = Number.isFinite(options.playbackRate) && options.playbackRate !== 0 ? options.playbackRate : 1;
|
|
8899
|
-
this.onTime = options.onTime;
|
|
8900
|
-
this.onEnd = options.onEnd;
|
|
8901
|
-
this.time = this.clamp(options.time ?? 0);
|
|
8902
|
-
this.cached = this.snapshot();
|
|
8903
|
-
}
|
|
8904
|
-
/** Current timeline length (ms). */
|
|
8905
|
-
get duration() {
|
|
8906
|
-
const d = typeof this.durationSource === "function" ? this.durationSource() : this.durationSource;
|
|
8907
|
-
return Number.isFinite(d) && d > 0 ? d : 0;
|
|
8908
|
-
}
|
|
8909
|
-
get currentTime() {
|
|
8910
|
-
return this.time;
|
|
8911
|
-
}
|
|
8912
|
-
get isPlaying() {
|
|
8913
|
-
return this.playing;
|
|
8914
|
-
}
|
|
8915
|
-
getState() {
|
|
8916
|
-
return this.cached;
|
|
8917
|
-
}
|
|
8918
|
-
subscribe(listener) {
|
|
8919
|
-
this.listeners.add(listener);
|
|
8920
|
-
return () => {
|
|
8921
|
-
this.listeners.delete(listener);
|
|
8922
|
-
};
|
|
8923
|
-
}
|
|
8924
|
-
/** Replaces the callbacks (hooks keep them current without recreating the player). */
|
|
8925
|
-
setCallbacks(callbacks) {
|
|
8926
|
-
this.onTime = callbacks.onTime;
|
|
8927
|
-
this.onEnd = callbacks.onEnd;
|
|
8928
|
-
}
|
|
8929
|
-
setDuration(duration) {
|
|
8930
|
-
this.durationSource = duration;
|
|
8931
|
-
this.time = this.clamp(this.time);
|
|
8932
|
-
this.emit(false);
|
|
8933
|
-
}
|
|
8934
|
-
setLoop(loop) {
|
|
8935
|
-
if (loop === this.loop) return;
|
|
8936
|
-
this.reanchor();
|
|
8937
|
-
this.loop = loop;
|
|
8938
|
-
this.emit(false);
|
|
8939
|
-
}
|
|
8940
|
-
setPlaybackRate(rate) {
|
|
8941
|
-
if (!Number.isFinite(rate) || rate === 0 || rate === this.rate) return;
|
|
8942
|
-
this.reanchor();
|
|
8943
|
-
this.rate = rate;
|
|
8944
|
-
this.emit(false);
|
|
8945
|
-
}
|
|
8946
|
-
/** Starts playing from the playhead (from the start again when a one-shot play had ended). */
|
|
8947
|
-
play() {
|
|
8948
|
-
if (this.playing) return;
|
|
8949
|
-
const d = this.duration;
|
|
8950
|
-
if (this.loop === "none" && d > 0) {
|
|
8951
|
-
if (this.rate > 0 && this.time >= d) this.time = 0;
|
|
8952
|
-
if (this.rate < 0 && this.time <= 0) this.time = d;
|
|
8953
|
-
}
|
|
8954
|
-
this.playing = true;
|
|
8955
|
-
this.scrubbing = false;
|
|
8956
|
-
this.anchorRaw = this.time;
|
|
8957
|
-
this.anchorAt = this.clock.now();
|
|
8958
|
-
this.emit(false);
|
|
8959
|
-
this.schedule();
|
|
8960
|
-
}
|
|
8961
|
-
pause() {
|
|
8962
|
-
if (!this.playing) return;
|
|
8963
|
-
this.tick(false);
|
|
8964
|
-
this.playing = false;
|
|
8965
|
-
this.generation++;
|
|
8966
|
-
this.emit(true);
|
|
8967
|
-
}
|
|
8968
|
-
toggle() {
|
|
8969
|
-
if (this.playing) this.pause();
|
|
8970
|
-
else this.play();
|
|
8971
|
-
}
|
|
8972
|
-
/** Pauses and returns to the start. */
|
|
8973
|
-
stop() {
|
|
8974
|
-
this.playing = false;
|
|
8975
|
-
this.generation++;
|
|
8976
|
-
this.seek(0);
|
|
8977
|
-
}
|
|
8978
|
-
/** Moves the playhead (clamped to the timeline); playback continues from there. */
|
|
8979
|
-
seek(time) {
|
|
8980
|
-
if (!Number.isFinite(time)) return;
|
|
8981
|
-
this.time = this.clamp(time);
|
|
8982
|
-
this.anchorRaw = this.time;
|
|
8983
|
-
this.anchorAt = this.clock.now();
|
|
8984
|
-
this.emit(true);
|
|
8985
|
-
}
|
|
8986
|
-
/** Seeks while dragging the playhead: playback pauses until `endScrub`. */
|
|
8987
|
-
scrub(time) {
|
|
8988
|
-
if (!this.scrubbing) {
|
|
8989
|
-
this.resumeAfterScrub = this.playing;
|
|
8990
|
-
if (this.playing) {
|
|
8991
|
-
this.playing = false;
|
|
8992
|
-
this.generation++;
|
|
8993
|
-
}
|
|
8994
|
-
this.scrubbing = true;
|
|
8995
|
-
}
|
|
8996
|
-
this.seek(time);
|
|
8997
|
-
}
|
|
8998
|
-
/** Ends a scrub, resuming playback if it was playing when the scrub began. */
|
|
8999
|
-
endScrub() {
|
|
9000
|
-
if (!this.scrubbing) return;
|
|
9001
|
-
this.scrubbing = false;
|
|
9002
|
-
const resume = this.resumeAfterScrub;
|
|
9003
|
-
this.resumeAfterScrub = false;
|
|
9004
|
-
if (resume) this.play();
|
|
9005
|
-
else this.emit(false);
|
|
9006
|
-
}
|
|
9007
|
-
/** Stops scheduling frames and drops listeners. */
|
|
9008
|
-
destroy() {
|
|
9009
|
-
this.playing = false;
|
|
9010
|
-
this.generation++;
|
|
9011
|
-
this.listeners.clear();
|
|
9012
|
-
}
|
|
9013
|
-
clamp(time) {
|
|
9014
|
-
return Math.min(this.duration, Math.max(0, Number.isFinite(time) ? time : 0));
|
|
9015
|
-
}
|
|
9016
|
-
reanchor() {
|
|
9017
|
-
if (!this.playing) return;
|
|
9018
|
-
this.tick(false);
|
|
9019
|
-
this.anchorRaw = this.rawNow();
|
|
9020
|
-
this.anchorAt = this.clock.now();
|
|
9021
|
-
}
|
|
9022
|
-
rawNow() {
|
|
9023
|
-
return this.anchorRaw + (this.clock.now() - this.anchorAt) * this.rate;
|
|
9024
|
-
}
|
|
9025
|
-
schedule() {
|
|
9026
|
-
const generation = this.generation;
|
|
9027
|
-
this.clock.frame().then(() => {
|
|
9028
|
-
if (generation !== this.generation || !this.playing) return;
|
|
9029
|
-
this.tick(true);
|
|
9030
|
-
if (this.playing) this.schedule();
|
|
9031
|
-
});
|
|
9032
|
-
}
|
|
9033
|
-
/** Advances the playhead to the clock's time; `notify` emits the change. */
|
|
9034
|
-
tick(notify) {
|
|
9035
|
-
if (!this.playing) return;
|
|
9036
|
-
const d = this.duration;
|
|
9037
|
-
const raw = this.rawNow();
|
|
9038
|
-
let ended = false;
|
|
9039
|
-
if (this.loop === "none" || d <= 0) {
|
|
9040
|
-
if (this.rate > 0 && raw >= d) {
|
|
9041
|
-
this.time = d;
|
|
9042
|
-
ended = true;
|
|
9043
|
-
} else if (this.rate < 0 && raw <= 0) {
|
|
9044
|
-
this.time = 0;
|
|
9045
|
-
ended = true;
|
|
9046
|
-
} else this.time = this.clamp(raw);
|
|
9047
|
-
} else {
|
|
9048
|
-
this.time = wrapAnimationTime(raw, d, this.loop);
|
|
9049
|
-
}
|
|
9050
|
-
if (ended) {
|
|
9051
|
-
this.playing = false;
|
|
9052
|
-
this.generation++;
|
|
9053
|
-
}
|
|
9054
|
-
if (notify || ended) this.emit(true);
|
|
9055
|
-
if (ended) this.onEnd?.();
|
|
9056
|
-
}
|
|
9057
|
-
snapshot() {
|
|
9058
|
-
return {
|
|
9059
|
-
time: this.time,
|
|
9060
|
-
playing: this.playing,
|
|
9061
|
-
scrubbing: this.scrubbing,
|
|
9062
|
-
loop: this.loop,
|
|
9063
|
-
playbackRate: this.rate,
|
|
9064
|
-
duration: this.duration
|
|
9065
|
-
};
|
|
9066
|
-
}
|
|
9067
|
-
emit(timeChanged) {
|
|
9068
|
-
const next = this.snapshot();
|
|
9069
|
-
const prev = this.cached;
|
|
9070
|
-
if (prev.time === next.time && prev.playing === next.playing && prev.scrubbing === next.scrubbing && prev.loop === next.loop && prev.playbackRate === next.playbackRate && prev.duration === next.duration) {
|
|
9071
|
-
return;
|
|
9072
|
-
}
|
|
9073
|
-
this.cached = next;
|
|
9074
|
-
if (timeChanged && prev.time !== next.time) this.onTime?.(next.time);
|
|
9075
|
-
for (const listener of this.listeners) listener(next);
|
|
9076
|
-
}
|
|
9077
|
-
};
|
|
9078
|
-
function createAnimationPlayer(options) {
|
|
9079
|
-
return new AnimationPlayer(options);
|
|
9080
|
-
}
|
|
9081
|
-
|
|
9082
8516
|
// src/canvas/animation/export.ts
|
|
9083
8517
|
function sampleAnimationFrames(doc, options = {}) {
|
|
9084
8518
|
const fps = options.fps ?? 30;
|
|
@@ -9109,22 +8543,22 @@ var CSS_ANIMATION_PROPERTIES = {
|
|
|
9109
8543
|
width: { css: "width", camel: "width" },
|
|
9110
8544
|
height: { css: "height", camel: "height" }
|
|
9111
8545
|
};
|
|
9112
|
-
var
|
|
8546
|
+
var round = (v) => Math.round(v * 1e3) / 1e3;
|
|
9113
8547
|
function cssValue(source, value, node, partner, partnerSource) {
|
|
9114
8548
|
if (source === "x" || source === "y") {
|
|
9115
8549
|
const dx = source === "x" ? value - node.position.x : partner !== void 0 ? partner - node.position.x : 0;
|
|
9116
8550
|
const dy = source === "y" ? value - node.position.y : partner !== void 0 && partnerSource === "y" ? partner - node.position.y : 0;
|
|
9117
|
-
return `${
|
|
8551
|
+
return `${round(dx)}px ${round(dy)}px`;
|
|
9118
8552
|
}
|
|
9119
8553
|
if (typeof value === "string") return value;
|
|
9120
8554
|
switch (source) {
|
|
9121
8555
|
case "rotation":
|
|
9122
|
-
return `${
|
|
8556
|
+
return `${round(value)}deg`;
|
|
9123
8557
|
case "scale":
|
|
9124
8558
|
case "opacity":
|
|
9125
|
-
return String(
|
|
8559
|
+
return String(round(value));
|
|
9126
8560
|
default:
|
|
9127
|
-
return `${
|
|
8561
|
+
return `${round(value)}px`;
|
|
9128
8562
|
}
|
|
9129
8563
|
}
|
|
9130
8564
|
var sameTimes = (a, b) => a.length === b.length && a.every((k, i) => Math.abs(k.time - b[i].time) < 1e-6 && JSON.stringify(k.easing ?? "linear") === JSON.stringify(b[i].easing ?? "linear"));
|
|
@@ -9184,7 +8618,7 @@ function getCssPropertyAnimations(nodes, nodeId, options = {}) {
|
|
|
9184
8618
|
if (sources.includes("motionPath")) {
|
|
9185
8619
|
const position = (t) => {
|
|
9186
8620
|
const moved = ANIMATABLE_PROPERTIES.find((p) => p.key === "motionPath").write(node, evalAt("motionPath", t));
|
|
9187
|
-
return `${
|
|
8621
|
+
return `${round(moved.position.x - node.position.x)}px ${round(moved.position.y - node.position.y)}px`;
|
|
9188
8622
|
};
|
|
9189
8623
|
out.push({ property: css, camel: camel2, sources, stops: sampledStops(duration, fps, allTimes, position), exact: false });
|
|
9190
8624
|
continue;
|
|
@@ -9219,7 +8653,7 @@ function timing(options, duration) {
|
|
|
9219
8653
|
const rate = options.playbackRate && Number.isFinite(options.playbackRate) && options.playbackRate !== 0 ? options.playbackRate : 1;
|
|
9220
8654
|
const loop = options.loop ?? "none";
|
|
9221
8655
|
return {
|
|
9222
|
-
duration:
|
|
8656
|
+
duration: round(duration / Math.abs(rate)),
|
|
9223
8657
|
iterations: loop === "none" ? 1 : Infinity,
|
|
9224
8658
|
direction: loop === "ping-pong" ? rate < 0 ? "alternate-reverse" : "alternate" : rate < 0 ? "reverse" : "normal"
|
|
9225
8659
|
};
|
|
@@ -9236,7 +8670,7 @@ function exportCssAnimation(nodes, nodeId, options = {}) {
|
|
|
9236
8670
|
for (const prop of props) {
|
|
9237
8671
|
const name = `${base}-${cssIdent(prop.property)}`;
|
|
9238
8672
|
const lines = prop.stops.map((s) => {
|
|
9239
|
-
const pct = `${
|
|
8673
|
+
const pct = `${round(s.offset * 100)}%`;
|
|
9240
8674
|
const easing = s.easing ? ` animation-timing-function: ${s.easing};` : "";
|
|
9241
8675
|
return ` ${pct} { ${prop.property}: ${s.value};${easing} }`;
|
|
9242
8676
|
});
|