resig.js
Version:
Universal reactive signal library with complete platform features: signals, animations, CRDTs, scheduling, DOM integration. Works identically across React, SolidJS, Svelte, Vue, and Qwik.
372 lines • 29.9 kB
JavaScript
;
/**
* Animation Composition System - Operadic Composition
* Following category-theoretic principles for animation composition
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.repeat = exports.stagger = exports.timeline = exports.sequence = exports.parallel = void 0;
const signal_1 = require("../core/signal");
const core_1 = require("./core");
// Parallel composition (Tensor product ⊗)
const parallel = (anim1, anim2) => {
const id = `parallel-${anim1.id}-${anim2.id}`;
const duration = Math.max(anim1.duration, anim2.duration);
// Combined state signal
const stateSignal = (0, signal_1.signal)({
value: { ...anim1.from, ...anim2.from },
progress: 0,
isComplete: false,
startTime: 0,
duration,
elapsedTime: 0,
});
const valueSignal = stateSignal.map((state) => state.value);
const progressSignal = stateSignal.map((state) => state.progress);
const isCompleteSignal = stateSignal.map((state) => state.isComplete);
// Sync animations
const syncAnimations = () => {
const state1 = anim1.state.value();
const state2 = anim2.state.value();
const combinedProgress = Math.max(state1.progress, state2.progress);
const combinedValue = { ...state1.value, ...state2.value };
const isComplete = state1.isComplete && state2.isComplete;
stateSignal._set({
value: combinedValue,
progress: combinedProgress,
isComplete,
startTime: Math.min(state1.startTime, state2.startTime),
duration,
elapsedTime: Math.max(state1.elapsedTime, state2.elapsedTime),
});
};
// Subscribe to both animations
anim1.state.subscribe(syncAnimations);
anim2.state.subscribe(syncAnimations);
const instance = {
id,
duration,
from: { ...anim1.from, ...anim2.from },
to: { ...anim1.to, ...anim2.to },
interpolator: ((from, to, _t) => {
// This is a simplified interpolator - in practice, you'd want more sophisticated handling
return { ...from, ...to };
}),
easing: anim1.easing, // Use first animation's easing
state: stateSignal,
value: valueSignal,
progress: progressSignal,
isComplete: isCompleteSignal,
first: anim1,
second: anim2,
map: (f, newInterpolator) => {
return (0, core_1.animation)(f(instance.from), f(instance.to), duration, newInterpolator, instance.easing);
},
ease: (newEasing) => {
return (0, exports.parallel)(anim1.ease(newEasing), anim2.ease(newEasing));
},
start: () => {
anim1.start();
anim2.start();
},
pause: () => {
anim1.pause();
anim2.pause();
},
resume: () => {
anim1.resume();
anim2.resume();
},
stop: () => {
anim1.stop();
anim2.stop();
},
seek: (progress) => {
anim1.seek(progress);
anim2.seek(progress);
},
onComplete: (callback) => {
return isCompleteSignal.subscribe((isComplete) => {
if (isComplete) {
callback(valueSignal.value());
}
});
},
onUpdate: (callback) => {
return stateSignal.subscribe(callback);
},
};
return instance;
};
exports.parallel = parallel;
// Sequential composition (Free monoidal category →)
const sequence = (first, second) => {
const id = `sequence-${first.id}-${second.id}`;
const duration = first.duration + second.duration;
const phaseSignal = (0, signal_1.signal)('first');
const stateSignal = (0, signal_1.signal)({
value: first.from,
progress: 0,
isComplete: false,
startTime: 0,
duration,
elapsedTime: 0,
});
const valueSignal = stateSignal.map((state) => state.value);
const progressSignal = stateSignal.map((state) => state.progress);
const isCompleteSignal = stateSignal.map((state) => state.isComplete);
let hasStartedSecond = false;
// Handle phase transitions
first.onComplete(() => {
if (!hasStartedSecond) {
hasStartedSecond = true;
phaseSignal._set('second');
second.start();
}
});
second.onComplete(() => {
phaseSignal._set('complete');
});
// Update combined state
const updateState = () => {
const phase = phaseSignal.value();
const firstState = first.state.value();
const secondState = second.state.value();
let combinedProgress;
let currentValue;
let isComplete;
if (phase === 'first') {
combinedProgress = firstState.progress * 0.5;
currentValue = firstState.value;
isComplete = false;
}
else if (phase === 'second') {
combinedProgress = 0.5 + secondState.progress * 0.5;
currentValue = secondState.value;
isComplete = secondState.isComplete;
}
else {
combinedProgress = 1;
currentValue = secondState.value;
isComplete = true;
}
stateSignal._set({
value: currentValue,
progress: combinedProgress,
isComplete,
startTime: firstState.startTime,
duration,
elapsedTime: firstState.elapsedTime + secondState.elapsedTime,
});
};
first.state.subscribe(updateState);
second.state.subscribe(updateState);
phaseSignal.subscribe(updateState);
const instance = {
id,
duration,
from: first.from,
to: second.to,
interpolator: ((from, to, t) => {
// Simplified interpolator for sequential animations
return t < 0.5 ? from : to;
}),
easing: first.easing,
state: stateSignal,
value: valueSignal,
progress: progressSignal,
isComplete: isCompleteSignal,
first,
second,
currentPhase: phaseSignal,
map: (f, newInterpolator) => {
return (0, core_1.animation)(f(instance.from), f(instance.to), duration, newInterpolator, instance.easing);
},
ease: (newEasing) => {
return (0, exports.sequence)(first.ease(newEasing), second.ease(newEasing));
},
start: () => {
hasStartedSecond = false;
phaseSignal._set('first');
first.start();
},
pause: () => {
first.pause();
second.pause();
},
resume: () => {
first.resume();
second.resume();
},
stop: () => {
first.stop();
second.stop();
phaseSignal._set('first');
hasStartedSecond = false;
},
seek: (progress) => {
const clampedProgress = Math.max(0, Math.min(1, progress));
if (clampedProgress < 0.5) {
// First animation
phaseSignal._set('first');
first.seek(clampedProgress * 2);
second.seek(0);
hasStartedSecond = false;
}
else {
// Second animation
phaseSignal._set('second');
first.seek(1);
second.seek((clampedProgress - 0.5) * 2);
hasStartedSecond = true;
}
},
onComplete: (callback) => {
return isCompleteSignal.subscribe((isComplete) => {
if (isComplete) {
callback(valueSignal.value());
}
});
},
onUpdate: (callback) => {
return stateSignal.subscribe(callback);
},
};
return instance;
};
exports.sequence = sequence;
// Timeline implementation for coordinating multiple animations
const timeline = () => {
const id = `timeline-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
let animations = [];
let duration = 0;
const progressSignal = (0, signal_1.signal)(0);
const isCompleteSignal = (0, signal_1.signal)(false);
let startTime = 0;
let isPaused = false;
let animationFrameId = null;
const updateTimeline = (currentTime) => {
if (isPaused)
return;
const elapsed = currentTime - startTime;
const progress = Math.min(elapsed / duration, 1);
progressSignal._set(progress);
// Update individual animations based on timeline progress
animations.forEach(({ animation: anim, offset }) => {
const animStart = offset;
const animEnd = offset + anim.duration;
if (elapsed >= animStart && elapsed <= animEnd) {
const animProgress = (elapsed - animStart) / anim.duration;
anim.seek(Math.max(0, Math.min(1, animProgress)));
}
else if (elapsed > animEnd) {
anim.seek(1);
}
});
if (progress >= 1) {
isCompleteSignal._set(true);
}
else {
animationFrameId = requestAnimationFrame(updateTimeline);
}
};
const recalculateDuration = () => {
duration = Math.max(...animations.map(({ animation: anim, offset }) => offset + anim.duration), 0);
};
const instance = {
id,
get duration() {
return duration;
},
progress: progressSignal,
isComplete: isCompleteSignal,
get animations() {
return [...animations];
},
add: (animation, offset = 0) => {
animations.push({ animation, offset });
recalculateDuration();
return instance;
},
remove: (animationId) => {
animations = animations.filter(({ animation: anim }) => anim.id !== animationId);
recalculateDuration();
return instance;
},
start: () => {
startTime = performance.now();
isPaused = false;
progressSignal._set(0);
isCompleteSignal._set(false);
animationFrameId = requestAnimationFrame(updateTimeline);
},
pause: () => {
isPaused = true;
if (animationFrameId) {
cancelAnimationFrame(animationFrameId);
animationFrameId = null;
}
animations.forEach(({ animation: anim }) => anim.pause());
},
resume: () => {
if (isPaused) {
const currentTime = performance.now();
const elapsed = progressSignal.value() * duration;
startTime = currentTime - elapsed;
isPaused = false;
animationFrameId = requestAnimationFrame(updateTimeline);
animations.forEach(({ animation: anim }) => anim.resume());
}
},
stop: () => {
isPaused = true;
if (animationFrameId) {
cancelAnimationFrame(animationFrameId);
animationFrameId = null;
}
progressSignal._set(0);
isCompleteSignal._set(false);
animations.forEach(({ animation: anim }) => anim.stop());
},
seek: (progress) => {
const clampedProgress = Math.max(0, Math.min(1, progress));
const elapsed = clampedProgress * duration;
progressSignal._set(clampedProgress);
animations.forEach(({ animation: anim, offset }) => {
const animStart = offset;
const animEnd = offset + anim.duration;
if (elapsed >= animStart && elapsed <= animEnd) {
const animProgress = (elapsed - animStart) / anim.duration;
anim.seek(animProgress);
}
else if (elapsed > animEnd) {
anim.seek(1);
}
else {
anim.seek(0);
}
});
},
};
return instance;
};
exports.timeline = timeline;
// Utility functions for common composition patterns
const stagger = (animations, staggerDelay) => {
const tl = (0, exports.timeline)();
animations.forEach((anim, index) => {
tl.add(anim, index * staggerDelay);
});
return tl;
};
exports.stagger = stagger;
const repeat = (animation, count, delay = 0) => {
const tl = (0, exports.timeline)();
for (let i = 0; i < count; i++) {
// Create a copy of the animation for each repetition
const animCopy = animation.map((v) => v, animation.interpolator);
tl.add(animCopy, i * (animation.duration + delay));
}
return tl;
};
exports.repeat = repeat;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tcG9zZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYW5pbWF0aW9uL2NvbXBvc2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7O0dBR0c7OztBQUVILDJDQUFnRDtBQUNoRCxpQ0FNZ0I7QUFnQ2hCLDBDQUEwQztBQUNuQyxNQUFNLFFBQVEsR0FBRyxDQUN0QixLQUFtQixFQUNuQixLQUFtQixFQUNNLEVBQUU7SUFDM0IsTUFBTSxFQUFFLEdBQUcsWUFBWSxLQUFLLENBQUMsRUFBRSxJQUFJLEtBQUssQ0FBQyxFQUFFLEVBQUUsQ0FBQztJQUM5QyxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxRQUFRLEVBQUUsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBRTFELHdCQUF3QjtJQUN4QixNQUFNLFdBQVcsR0FBRyxJQUFBLGVBQU0sRUFBd0I7UUFDaEQsS0FBSyxFQUFFLEVBQUUsR0FBRyxLQUFLLENBQUMsSUFBSSxFQUFFLEdBQUcsS0FBSyxDQUFDLElBQUksRUFBVztRQUNoRCxRQUFRLEVBQUUsQ0FBQztRQUNYLFVBQVUsRUFBRSxLQUFLO1FBQ2pCLFNBQVMsRUFBRSxDQUFDO1FBQ1osUUFBUTtRQUNSLFdBQVcsRUFBRSxDQUFDO0tBQ2YsQ0FBQyxDQUFDO0lBRUgsTUFBTSxXQUFXLEdBQUcsV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzVELE1BQU0sY0FBYyxHQUFHLFdBQVcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUNsRSxNQUFNLGdCQUFnQixHQUFHLFdBQVcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUV0RSxrQkFB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