Add .gitignore to exclude all node packages and lock files

This commit is contained in:
Adolfo Reyna
2026-02-23 21:56:04 -05:00
parent faae96c9ed
commit dcc5c6c044
9747 changed files with 1555105 additions and 2 deletions
@@ -0,0 +1,2 @@
import type { RemotionAnimatedImageProps } from './props';
export declare const AnimatedImage: import("react").ForwardRefExoticComponent<RemotionAnimatedImageProps & import("react").RefAttributes<HTMLCanvasElement>>;
@@ -0,0 +1,114 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AnimatedImage = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const cancel_render_js_1 = require("../cancel-render.js");
const use_current_frame_js_1 = require("../use-current-frame.js");
const use_delay_render_js_1 = require("../use-delay-render.js");
const use_video_config_js_1 = require("../use-video-config.js");
const canvas_1 = require("./canvas");
const decode_image_js_1 = require("./decode-image.js");
const resolve_image_source_1 = require("./resolve-image-source");
exports.AnimatedImage = (0, react_1.forwardRef)(({ src, width, height, onError, loopBehavior = 'loop', playbackRate = 1, fit = 'fill', ...props }, canvasRef) => {
const mountState = (0, react_1.useRef)({ isMounted: true });
(0, react_1.useEffect)(() => {
const { current } = mountState;
current.isMounted = true;
return () => {
current.isMounted = false;
};
}, []);
const resolvedSrc = (0, resolve_image_source_1.resolveAnimatedImageSource)(src);
const [imageDecoder, setImageDecoder] = (0, react_1.useState)(null);
const { delayRender, continueRender } = (0, use_delay_render_js_1.useDelayRender)();
const [decodeHandle] = (0, react_1.useState)(() => delayRender(`Rendering <AnimatedImage/> with src="${resolvedSrc}"`));
const frame = (0, use_current_frame_js_1.useCurrentFrame)();
const { fps } = (0, use_video_config_js_1.useVideoConfig)();
const currentTime = frame / playbackRate / fps;
const currentTimeRef = (0, react_1.useRef)(currentTime);
currentTimeRef.current = currentTime;
const ref = (0, react_1.useRef)(null);
(0, react_1.useImperativeHandle)(canvasRef, () => {
var _a;
const c = (_a = ref.current) === null || _a === void 0 ? void 0 : _a.getCanvas();
if (!c) {
throw new Error('Canvas ref is not set');
}
return c;
}, []);
const [initialLoopBehavior] = (0, react_1.useState)(() => loopBehavior);
(0, react_1.useEffect)(() => {
const controller = new AbortController();
(0, decode_image_js_1.decodeImage)({
resolvedSrc,
signal: controller.signal,
currentTime: currentTimeRef.current,
initialLoopBehavior,
})
.then((d) => {
setImageDecoder(d);
continueRender(decodeHandle);
})
.catch((err) => {
if (err.name === 'AbortError') {
continueRender(decodeHandle);
return;
}
if (onError) {
onError === null || onError === void 0 ? void 0 : onError(err);
continueRender(decodeHandle);
}
else {
(0, cancel_render_js_1.cancelRender)(err);
}
});
return () => {
controller.abort();
};
}, [
resolvedSrc,
decodeHandle,
onError,
initialLoopBehavior,
continueRender,
]);
(0, react_1.useLayoutEffect)(() => {
if (!imageDecoder) {
return;
}
const delay = delayRender(`Rendering frame at ${currentTime} of <AnimatedImage src="${src}"/>`);
imageDecoder
.getFrame(currentTime, loopBehavior)
.then((videoFrame) => {
var _a, _b;
if (mountState.current.isMounted) {
if (videoFrame === null) {
(_a = ref.current) === null || _a === void 0 ? void 0 : _a.clear();
}
else {
(_b = ref.current) === null || _b === void 0 ? void 0 : _b.draw(videoFrame.frame);
}
}
continueRender(delay);
})
.catch((err) => {
if (onError) {
onError(err);
continueRender(delay);
}
else {
(0, cancel_render_js_1.cancelRender)(err);
}
});
}, [
currentTime,
imageDecoder,
loopBehavior,
onError,
src,
continueRender,
delayRender,
]);
return ((0, jsx_runtime_1.jsx)(canvas_1.Canvas, { ref: ref, width: width, height: height, fit: fit, ...props }));
});
@@ -0,0 +1,16 @@
import React from 'react';
import type { AnimatedImageFillMode } from './props';
type Props = {
readonly width?: number;
readonly height?: number;
readonly fit: AnimatedImageFillMode;
readonly className?: string;
readonly style?: React.CSSProperties;
};
export type AnimatedImageCanvasRef = {
readonly draw: (imageData: VideoFrame) => void;
readonly getCanvas: () => HTMLCanvasElement | null;
clear: () => void;
};
export declare const Canvas: React.ForwardRefExoticComponent<Props & React.RefAttributes<AnimatedImageCanvasRef>>;
export {};
@@ -0,0 +1,132 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.Canvas = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = __importStar(require("react"));
const calcArgs = (fit, frameSize, canvasSize) => {
switch (fit) {
case 'fill': {
return [
0,
0,
frameSize.width,
frameSize.height,
0,
0,
canvasSize.width,
canvasSize.height,
];
}
case 'contain': {
const ratio = Math.min(canvasSize.width / frameSize.width, canvasSize.height / frameSize.height);
const centerX = (canvasSize.width - frameSize.width * ratio) / 2;
const centerY = (canvasSize.height - frameSize.height * ratio) / 2;
return [
0,
0,
frameSize.width,
frameSize.height,
centerX,
centerY,
frameSize.width * ratio,
frameSize.height * ratio,
];
}
case 'cover': {
const ratio = Math.max(canvasSize.width / frameSize.width, canvasSize.height / frameSize.height);
const centerX = (canvasSize.width - frameSize.width * ratio) / 2;
const centerY = (canvasSize.height - frameSize.height * ratio) / 2;
return [
0,
0,
frameSize.width,
frameSize.height,
centerX,
centerY,
frameSize.width * ratio,
frameSize.height * ratio,
];
}
default:
throw new Error('Unknown fit: ' + fit);
}
};
const CanvasRefForwardingFunction = ({ width, height, fit, className, style }, ref) => {
const canvasRef = (0, react_1.useRef)(null);
const draw = (0, react_1.useCallback)((imageData) => {
var _a;
const canvas = canvasRef.current;
const canvasWidth = width !== null && width !== void 0 ? width : imageData.displayWidth;
const canvasHeight = height !== null && height !== void 0 ? height : imageData.displayHeight;
if (!canvas) {
throw new Error('Canvas ref is not set');
}
const ctx = (_a = canvasRef.current) === null || _a === void 0 ? void 0 : _a.getContext('2d');
if (!ctx) {
throw new Error('Could not get 2d context');
}
canvas.width = canvasWidth;
canvas.height = canvasHeight;
ctx.drawImage(imageData, ...calcArgs(fit, {
height: imageData.displayHeight,
width: imageData.displayWidth,
}, {
width: canvasWidth,
height: canvasHeight,
}));
}, [fit, height, width]);
(0, react_1.useImperativeHandle)(ref, () => {
return {
draw,
getCanvas: () => {
if (!canvasRef.current) {
throw new Error('Canvas ref is not set');
}
return canvasRef.current;
},
clear: () => {
var _a;
const ctx = (_a = canvasRef.current) === null || _a === void 0 ? void 0 : _a.getContext('2d');
if (!ctx) {
throw new Error('Could not get 2d context');
}
ctx.clearRect(0, 0, canvasRef.current.width, canvasRef.current.height);
},
};
}, [draw]);
return (0, jsx_runtime_1.jsx)("canvas", { ref: canvasRef, className: className, style: style });
};
exports.Canvas = react_1.default.forwardRef(CanvasRefForwardingFunction);
@@ -0,0 +1,16 @@
import type { RemotionAnimatedImageLoopBehavior } from './props';
export type AnimatedImageCacheItem = {
timeInSeconds: number;
frameIndex: number;
frame: VideoFrame | null;
};
export type RemotionImageDecoder = {
getFrame: (i: number, loopBehavior: RemotionAnimatedImageLoopBehavior) => Promise<AnimatedImageCacheItem | null>;
frameCount: number;
};
export declare const decodeImage: ({ resolvedSrc, signal, currentTime, initialLoopBehavior, }: {
resolvedSrc: string;
signal: AbortSignal;
currentTime: number;
initialLoopBehavior: RemotionAnimatedImageLoopBehavior;
}) => Promise<RemotionImageDecoder>;
@@ -0,0 +1,145 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.decodeImage = void 0;
const CACHE_SIZE = 5;
const getActualTime = ({ loopBehavior, durationFound, timeInSec, }) => {
return loopBehavior === 'loop'
? durationFound
? timeInSec % durationFound
: timeInSec
: Math.min(timeInSec, durationFound || Infinity);
};
const decodeImage = async ({ resolvedSrc, signal, currentTime, initialLoopBehavior, }) => {
if (typeof ImageDecoder === 'undefined') {
throw new Error('Your browser does not support the WebCodecs ImageDecoder API.');
}
const res = await fetch(resolvedSrc, { signal });
const { body } = res;
if (!body) {
throw new Error('Got no body');
}
const decoder = new ImageDecoder({
data: body,
type: res.headers.get('Content-Type') || 'image/gif',
});
await decoder.completed;
const { selectedTrack } = decoder.tracks;
if (!selectedTrack) {
throw new Error('No selected track');
}
const cache = [];
let durationFound = null;
const getFrameByIndex = async (frameIndex) => {
const foundInCache = cache.find((c) => c.frameIndex === frameIndex);
if (foundInCache && foundInCache.frame) {
return foundInCache;
}
const frame = await decoder.decode({
frameIndex,
completeFramesOnly: true,
});
if (foundInCache) {
foundInCache.frame = frame.image;
}
else {
cache.push({
frame: frame.image,
frameIndex,
timeInSeconds: frame.image.timestamp / 1000000,
});
}
return {
frame: frame.image,
frameIndex,
timeInSeconds: frame.image.timestamp / 1000000,
};
};
const clearCache = (closeToTimeInSec) => {
const itemsInCache = cache.filter((c) => c.frame);
const sortByClosestToCurrentTime = itemsInCache.sort((a, b) => {
const aDiff = Math.abs(a.timeInSeconds - closeToTimeInSec);
const bDiff = Math.abs(b.timeInSeconds - closeToTimeInSec);
return aDiff - bDiff;
});
for (let i = 0; i < sortByClosestToCurrentTime.length; i++) {
if (i < CACHE_SIZE) {
continue;
}
const item = sortByClosestToCurrentTime[i];
item.frame = null;
}
};
const ensureFrameBeforeAndAfter = async ({ timeInSec, loopBehavior, }) => {
const actualTimeInSec = getActualTime({
durationFound,
loopBehavior,
timeInSec,
});
const framesBefore = cache.filter((c) => c.timeInSeconds <= actualTimeInSec);
const biggestIndex = framesBefore
.map((c) => c.frameIndex)
.reduce((a, b) => Math.max(a, b), 0);
let i = biggestIndex;
while (true) {
const f = await getFrameByIndex(i);
i++;
if (!f.frame) {
throw new Error('No frame found');
}
if (!f.frame.duration) {
// non-animated, or AVIF in firefox
break;
}
if (i === selectedTrack.frameCount && durationFound === null) {
const duration = (f.frame.timestamp + f.frame.duration) / 1000000;
durationFound = duration;
}
if (f.timeInSeconds > actualTimeInSec || i === selectedTrack.frameCount) {
break;
}
}
// If close to end, also cache first frame for smooth wrap around
if (selectedTrack.frameCount - biggestIndex < 3 &&
loopBehavior === 'loop') {
await getFrameByIndex(0);
}
clearCache(actualTimeInSec);
};
// Twice because might be over total duration
await ensureFrameBeforeAndAfter({
timeInSec: currentTime,
loopBehavior: initialLoopBehavior,
});
await ensureFrameBeforeAndAfter({
timeInSec: currentTime,
loopBehavior: initialLoopBehavior,
});
const getFrame = async (timeInSec, loopBehavior) => {
if (durationFound !== null &&
timeInSec > durationFound &&
loopBehavior === 'clear-after-finish') {
return null;
}
const actualTimeInSec = getActualTime({
loopBehavior,
durationFound,
timeInSec,
});
await ensureFrameBeforeAndAfter({ timeInSec: actualTimeInSec, loopBehavior });
const itemsInCache = cache.filter((c) => c.frame);
const closest = itemsInCache.reduce((a, b) => {
const aDiff = Math.abs(a.timeInSeconds - actualTimeInSec);
const bDiff = Math.abs(b.timeInSeconds - actualTimeInSec);
return aDiff < bDiff ? a : b;
});
if (!closest.frame) {
throw new Error('No frame found');
}
return closest;
};
return {
getFrame,
frameCount: selectedTrack.frameCount,
};
};
exports.decodeImage = decodeImage;
@@ -0,0 +1 @@
export { AnimatedImage } from './AnimatedImage';
@@ -0,0 +1,5 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AnimatedImage = void 0;
var AnimatedImage_1 = require("./AnimatedImage");
Object.defineProperty(exports, "AnimatedImage", { enumerable: true, get: function () { return AnimatedImage_1.AnimatedImage; } });
@@ -0,0 +1,14 @@
export type RemotionAnimatedImageLoopBehavior = 'loop' | 'pause-after-finish' | 'clear-after-finish';
export type RemotionAnimatedImageProps = {
src: string;
width?: number;
height?: number;
onError?: (error: Error) => void;
fit?: AnimatedImageFillMode;
playbackRate?: number;
style?: React.CSSProperties;
loopBehavior?: RemotionAnimatedImageLoopBehavior;
id?: string;
className?: string;
};
export type AnimatedImageFillMode = 'contain' | 'cover' | 'fill';
@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1 @@
export declare const resolveAnimatedImageSource: (src: string) => string;
@@ -0,0 +1,10 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.resolveAnimatedImageSource = void 0;
const resolveAnimatedImageSource = (src) => {
if (typeof window === 'undefined') {
return src;
}
return new URL(src, window.origin).href;
};
exports.resolveAnimatedImageSource = resolveAnimatedImageSource;