remotion 4.0.525 → 4.0.527

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.
@@ -74,7 +74,6 @@ export declare const absoluteFillSchema: {
74
74
  readonly type: "font-weight";
75
75
  readonly default: 400;
76
76
  readonly description: "Font weight";
77
- readonly keyframable: false;
78
77
  };
79
78
  readonly 'style.fontStyle': {
80
79
  readonly type: "enum";
package/dist/cjs/Img.d.ts CHANGED
@@ -8,6 +8,7 @@ export type ImgProps = NativeImgProps & {
8
8
  readonly delayRenderRetries?: number;
9
9
  readonly delayRenderTimeoutInMilliseconds?: number;
10
10
  readonly onImageFrame?: (imageElement: HTMLImageElement) => void;
11
+ readonly onImageError?: (error: Error) => void;
11
12
  readonly src: string;
12
13
  readonly effects?: EffectsProp;
13
14
  readonly showInTimeline?: boolean;
@@ -225,6 +226,7 @@ export declare const Img: React.ComponentType<NativeImgProps & {
225
226
  readonly delayRenderRetries?: number | undefined;
226
227
  readonly delayRenderTimeoutInMilliseconds?: number | undefined;
227
228
  readonly onImageFrame?: ((imageElement: HTMLImageElement) => void) | undefined;
229
+ readonly onImageError?: ((error: Error) => void) | undefined;
228
230
  readonly src: string;
229
231
  readonly effects?: EffectsProp | undefined;
230
232
  readonly showInTimeline?: boolean | undefined;
package/dist/cjs/Img.js CHANGED
@@ -22,7 +22,7 @@ const with_interactivity_schema_js_1 = require("./with-interactivity-schema.js")
22
22
  function exponentialBackoff(errorCount) {
23
23
  return 1000 * 2 ** (errorCount - 1);
24
24
  }
25
- const ImgContent = ({ onError, maxRetries = 2, src, pauseWhenLoading, delayRenderRetries, delayRenderTimeoutInMilliseconds, onImageFrame, crossOrigin, decoding, ref, refForOutline, ...props }) => {
25
+ const ImgContent = ({ onError, onImageError, maxRetries = 2, src, pauseWhenLoading, delayRenderRetries, delayRenderTimeoutInMilliseconds, onImageFrame, crossOrigin, decoding, ref, refForOutline, ...props }) => {
26
26
  const imageRef = (0, react_1.useRef)(null);
27
27
  const errors = (0, react_1.useRef)({});
28
28
  const { delayPlayback } = (0, use_buffer_state_js_1.useBufferState)();
@@ -67,34 +67,36 @@ const ImgContent = ({ onError, maxRetries = 2, src, pauseWhenLoading, delayRende
67
67
  const isPremounting = Boolean(sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.premounting);
68
68
  const isPostmounting = Boolean(sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.postmounting);
69
69
  const didGetError = (0, react_1.useCallback)((e) => {
70
- var _a, _b, _c, _d, _e, _f, _g;
71
- var _h, _j, _k, _l;
70
+ var _a, _b, _c, _d, _e, _f, _g, _h;
71
+ var _j, _k, _l, _m;
72
72
  if (!errors.current) {
73
73
  return;
74
74
  }
75
75
  errors.current[(_a = imageRef.current) === null || _a === void 0 ? void 0 : _a.src] =
76
- ((_h = errors.current[(_b = imageRef.current) === null || _b === void 0 ? void 0 : _b.src]) !== null && _h !== void 0 ? _h : 0) + 1;
77
- if (onError &&
78
- ((_j = errors.current[(_c = imageRef.current) === null || _c === void 0 ? void 0 : _c.src]) !== null && _j !== void 0 ? _j : 0) > maxRetries) {
79
- onError(e);
76
+ ((_j = errors.current[(_b = imageRef.current) === null || _b === void 0 ? void 0 : _b.src]) !== null && _j !== void 0 ? _j : 0) + 1;
77
+ if ((onError || onImageError) &&
78
+ ((_k = errors.current[(_c = imageRef.current) === null || _c === void 0 ? void 0 : _c.src]) !== null && _k !== void 0 ? _k : 0) > maxRetries) {
79
+ onError === null || onError === void 0 ? void 0 : onError(e);
80
+ onImageError === null || onImageError === void 0 ? void 0 : onImageError(new Error('Error loading image with src: ' +
81
+ (0, truncate_src_for_label_js_1.truncateSrcForLabel)((_d = imageRef.current) === null || _d === void 0 ? void 0 : _d.src)));
80
82
  return;
81
83
  }
82
- if (((_k = errors.current[(_d = imageRef.current) === null || _d === void 0 ? void 0 : _d.src]) !== null && _k !== void 0 ? _k : 0) <= maxRetries) {
83
- const backoff = exponentialBackoff((_l = errors.current[(_e = imageRef.current) === null || _e === void 0 ? void 0 : _e.src]) !== null && _l !== void 0 ? _l : 0);
84
+ if (((_l = errors.current[(_e = imageRef.current) === null || _e === void 0 ? void 0 : _e.src]) !== null && _l !== void 0 ? _l : 0) <= maxRetries) {
85
+ const backoff = exponentialBackoff((_m = errors.current[(_f = imageRef.current) === null || _f === void 0 ? void 0 : _f.src]) !== null && _m !== void 0 ? _m : 0);
84
86
  // eslint-disable-next-line no-console
85
- console.warn(`Could not load image with source ${(0, truncate_src_for_label_js_1.truncateSrcForLabel)((_f = imageRef.current) === null || _f === void 0 ? void 0 : _f.src)}, retrying again in ${backoff}ms`);
87
+ console.warn(`Could not load image with source ${(0, truncate_src_for_label_js_1.truncateSrcForLabel)((_g = imageRef.current) === null || _g === void 0 ? void 0 : _g.src)}, retrying again in ${backoff}ms`);
86
88
  retryIn(backoff);
87
89
  return;
88
90
  }
89
91
  try {
90
92
  cancelRender('Error loading image with src: ' +
91
- (0, truncate_src_for_label_js_1.truncateSrcForLabel)((_g = imageRef.current) === null || _g === void 0 ? void 0 : _g.src));
93
+ (0, truncate_src_for_label_js_1.truncateSrcForLabel)((_h = imageRef.current) === null || _h === void 0 ? void 0 : _h.src));
92
94
  }
93
- catch (_m) {
95
+ catch (_o) {
94
96
  // cancelRender() intentionally throws after storing the error in scope.
95
97
  // In async image callbacks, we rely on the stored error for renderer propagation.
96
98
  }
97
- }, [cancelRender, maxRetries, onError, retryIn]);
99
+ }, [cancelRender, maxRetries, onError, onImageError, retryIn]);
98
100
  if (typeof window !== 'undefined') {
99
101
  // eslint-disable-next-line react-hooks/rules-of-hooks
100
102
  (0, react_1.useLayoutEffect)(() => {
@@ -200,6 +202,10 @@ const NativeImgInner = ({ hidden, name, showInTimeline, src, from, trimBefore, d
200
202
  if (!src) {
201
203
  throw new Error('No "src" prop was passed to <Img>.');
202
204
  }
205
+ const isMedia = (0, react_1.useMemo)(() => ({
206
+ type: 'image',
207
+ src,
208
+ }), [src]);
203
209
  const { effectivePostmountFor, effectivePremountFor, freezeFrame, isPremountingOrPostmounting, postmountingActive, premountingActive, premountingStyle, } = (0, use_premounting_js_1.usePremounting)({
204
210
  from: from !== null && from !== void 0 ? from : 0,
205
211
  durationInFrames: durationInFrames !== null && durationInFrames !== void 0 ? durationInFrames : Infinity,
@@ -218,7 +224,7 @@ const NativeImgInner = ({ hidden, name, showInTimeline, src, from, trimBefore, d
218
224
  style: premountingStyle,
219
225
  componentName: '<Img />',
220
226
  });
221
- return (jsx_runtime_1.jsx(freeze_js_1.Freeze, { frame: freezeFrame, active: isPremountingOrPostmounting, children: jsx_runtime_1.jsx(Sequence_js_1.Sequence, { layout: "none", from: from !== null && from !== void 0 ? from : 0, trimBefore: trimBefore, durationInFrames: durationInFrames !== null && durationInFrames !== void 0 ? durationInFrames : Infinity, freeze: freeze, _remotionInternalDocumentationLink: "https://www.remotion.dev/docs/img", _remotionInternalIsMedia: { type: 'image', src }, _remotionInternalPremountDisplay: effectivePremountFor || null, _remotionInternalPostmountDisplay: effectivePostmountFor || null, _remotionInternalIsPremounting: premountingActive, _remotionInternalIsPostmounting: postmountingActive, name: name !== null && name !== void 0 ? name : '<Img>', controls: controls, showInTimeline: showInTimeline !== null && showInTimeline !== void 0 ? showInTimeline : true, hidden: hidden, outlineRef: refForOutline, children: jsx_runtime_1.jsx(ImgContent, { src: src, refForOutline: refForOutline, style: croppedStyle !== null && croppedStyle !== void 0 ? croppedStyle : undefined, ...props }) }) }));
227
+ return (jsx_runtime_1.jsx(freeze_js_1.Freeze, { frame: freezeFrame, active: isPremountingOrPostmounting, children: jsx_runtime_1.jsx(Sequence_js_1.Sequence, { layout: "none", from: from !== null && from !== void 0 ? from : 0, trimBefore: trimBefore, durationInFrames: durationInFrames !== null && durationInFrames !== void 0 ? durationInFrames : Infinity, freeze: freeze, _remotionInternalDocumentationLink: "https://www.remotion.dev/docs/img", _remotionInternalIsMedia: isMedia, _remotionInternalPremountDisplay: effectivePremountFor || null, _remotionInternalPostmountDisplay: effectivePostmountFor || null, _remotionInternalIsPremounting: premountingActive, _remotionInternalIsPostmounting: postmountingActive, name: name !== null && name !== void 0 ? name : '<Img>', controls: controls, showInTimeline: showInTimeline !== null && showInTimeline !== void 0 ? showInTimeline : true, hidden: hidden, outlineRef: refForOutline, children: jsx_runtime_1.jsx(ImgContent, { src: src, refForOutline: refForOutline, style: croppedStyle !== null && croppedStyle !== void 0 ? croppedStyle : undefined, ...props }) }) }));
222
228
  };
223
229
  const CanvasImageWithPrivateProps = index_js_1.CanvasImage;
224
230
  exports.imgSchema = {
@@ -239,7 +245,6 @@ exports.imgSchema = {
239
245
  };
240
246
  const imgCanvasFallbackIncompatibleProps = new Set([
241
247
  'alt',
242
- 'crossOrigin',
243
248
  'decoding',
244
249
  'fetchPriority',
245
250
  'loading',
@@ -276,12 +281,12 @@ const getFitFromObjectFit = (style) => {
276
281
  }
277
282
  return undefined;
278
283
  };
279
- const ImgInner = ({ effects = [], ref, hidden, name, showInTimeline, src, from, trimBefore, durationInFrames, freeze, premountFor, postmountFor, styleWhilePremounted, styleWhilePostmounted, controls, width, height, className, style, cropLeft, cropRight, cropTop, cropBottom, id, pauseWhenLoading, maxRetries, delayRenderRetries, delayRenderTimeoutInMilliseconds, ...props }) => {
284
+ const ImgInner = ({ effects = [], ref, hidden, name, showInTimeline, src, from, trimBefore, durationInFrames, freeze, premountFor, postmountFor, styleWhilePremounted, styleWhilePostmounted, controls, width, height, className, style, cropLeft, cropRight, cropTop, cropBottom, id, pauseWhenLoading, maxRetries, delayRenderRetries, delayRenderTimeoutInMilliseconds, onImageError, ...props }) => {
280
285
  var _a;
281
286
  const refForOutline = (0, react_1.useRef)(null);
282
287
  const shouldPauseWhenLoading = (0, v5_flag_js_1.resolveV5Default)(pauseWhenLoading);
283
288
  if (effects.length === 0) {
284
- return (jsx_runtime_1.jsx(NativeImgInner, { ...props, ref: ref, hidden: hidden, name: name, showInTimeline: showInTimeline, src: src, from: from, trimBefore: trimBefore, durationInFrames: durationInFrames, freeze: freeze, premountFor: premountFor, postmountFor: postmountFor, styleWhilePremounted: styleWhilePremounted, styleWhilePostmounted: styleWhilePostmounted, controls: controls, width: width, height: height, className: className, style: style, cropLeft: cropLeft, cropRight: cropRight, cropTop: cropTop, cropBottom: cropBottom, id: id, pauseWhenLoading: shouldPauseWhenLoading, maxRetries: maxRetries, delayRenderRetries: delayRenderRetries, delayRenderTimeoutInMilliseconds: delayRenderTimeoutInMilliseconds, outlineRef: refForOutline }));
289
+ return (jsx_runtime_1.jsx(NativeImgInner, { ...props, ref: ref, hidden: hidden, name: name, showInTimeline: showInTimeline, src: src, from: from, trimBefore: trimBefore, durationInFrames: durationInFrames, freeze: freeze, premountFor: premountFor, postmountFor: postmountFor, styleWhilePremounted: styleWhilePremounted, styleWhilePostmounted: styleWhilePostmounted, controls: controls, width: width, height: height, className: className, style: style, cropLeft: cropLeft, cropRight: cropRight, cropTop: cropTop, cropBottom: cropBottom, id: id, pauseWhenLoading: shouldPauseWhenLoading, maxRetries: maxRetries, delayRenderRetries: delayRenderRetries, delayRenderTimeoutInMilliseconds: delayRenderTimeoutInMilliseconds, onImageError: onImageError, outlineRef: refForOutline }));
285
290
  }
286
291
  if (!src) {
287
292
  throw new Error('No "src" prop was passed to <Img>.');
@@ -296,7 +301,7 @@ const ImgInner = ({ effects = [], ref, hidden, name, showInTimeline, src, from,
296
301
  const canvasHeight = typeof height === 'number' ? height : undefined;
297
302
  const canvasProps = props;
298
303
  const canvasFit = (_a = getFitFromObjectFit(style)) !== null && _a !== void 0 ? _a : 'fill';
299
- return (jsx_runtime_1.jsx(CanvasImageWithPrivateProps, { src: src, width: canvasWidth, height: canvasHeight, fit: canvasFit, effects: effects, className: className, style: style, cropLeft: cropLeft, cropRight: cropRight, cropTop: cropTop, cropBottom: cropBottom, id: id, pauseWhenLoading: shouldPauseWhenLoading, maxRetries: maxRetries, delayRenderRetries: delayRenderRetries, delayRenderTimeoutInMilliseconds: delayRenderTimeoutInMilliseconds, from: from, trimBefore: trimBefore, durationInFrames: durationInFrames, freeze: freeze, premountFor: premountFor, postmountFor: postmountFor, styleWhilePremounted: styleWhilePremounted, styleWhilePostmounted: styleWhilePostmounted, hidden: hidden, name: name !== null && name !== void 0 ? name : '<Img>', showInTimeline: showInTimeline, _remotionInternalDocumentationLink: "https://www.remotion.dev/docs/img", _remotionInternalCropComponentName: "<Img />", controls: controls, outlineRef: refForOutline, ...canvasProps }));
304
+ return (jsx_runtime_1.jsx(CanvasImageWithPrivateProps, { src: src, width: canvasWidth, height: canvasHeight, fit: canvasFit, effects: effects, className: className, style: style, cropLeft: cropLeft, cropRight: cropRight, cropTop: cropTop, cropBottom: cropBottom, id: id, onError: onImageError, pauseWhenLoading: shouldPauseWhenLoading, maxRetries: maxRetries, delayRenderRetries: delayRenderRetries, delayRenderTimeoutInMilliseconds: delayRenderTimeoutInMilliseconds, from: from, trimBefore: trimBefore, durationInFrames: durationInFrames, freeze: freeze, premountFor: premountFor, postmountFor: postmountFor, styleWhilePremounted: styleWhilePremounted, styleWhilePostmounted: styleWhilePostmounted, hidden: hidden, name: name !== null && name !== void 0 ? name : '<Img>', showInTimeline: showInTimeline, _remotionInternalDocumentationLink: "https://www.remotion.dev/docs/img", _remotionInternalCropComponentName: "<Img />", controls: controls, outlineRef: refForOutline, ...canvasProps }));
300
305
  };
301
306
  /*
302
307
  * @description Works just like a regular HTML img tag. When you use the <Img> tag, Remotion will ensure that the image is loaded before rendering the frame.
@@ -126,7 +126,6 @@ export declare const Interactive: {
126
126
  readonly type: "font-weight";
127
127
  readonly default: 400;
128
128
  readonly description: "Font weight";
129
- readonly keyframable: false;
130
129
  };
131
130
  readonly 'style.fontStyle': {
132
131
  readonly type: "enum";
@@ -219,6 +219,7 @@ export declare const canvasImageSchema: {
219
219
  };
220
220
  export declare const CanvasImage: import("react").ComponentType<import("../Interactive.js").InteractiveBaseProps & import("../Interactive.js").InteractiveCropProps & import("../Interactive.js").InteractivePremountProps & CanvasImageCanvasProps & {
221
221
  readonly src: string;
222
+ readonly crossOrigin?: "" | "anonymous" | "use-credentials" | undefined;
222
223
  readonly width?: number | undefined;
223
224
  readonly height?: number | undefined;
224
225
  readonly fit?: import("../calculate-image-fit.js").ImageFit | undefined;
@@ -53,7 +53,7 @@ const makeAbortError = () => {
53
53
  error.name = 'AbortError';
54
54
  return error;
55
55
  };
56
- const loadImage = ({ src, signal, }) => {
56
+ const loadImage = ({ src, signal, crossOrigin, }) => {
57
57
  return new Promise((resolve, reject) => {
58
58
  const image = new Image();
59
59
  let settled = false;
@@ -94,7 +94,7 @@ const loadImage = ({ src, signal, }) => {
94
94
  onAbort();
95
95
  return;
96
96
  }
97
- image.crossOrigin = 'anonymous';
97
+ image.crossOrigin = crossOrigin !== null && crossOrigin !== void 0 ? crossOrigin : 'anonymous';
98
98
  image.src = src;
99
99
  });
100
100
  };
@@ -109,7 +109,7 @@ const waitForNextFrame = ({ onFrame, }) => {
109
109
  const frame = requestAnimationFrame(onFrame);
110
110
  return () => cancelAnimationFrame(frame);
111
111
  };
112
- const CanvasImageContent = (0, react_1.forwardRef)(({ src, width, height, fit = 'fill', effects, controls, onError, className, style, id, pauseWhenLoading, maxRetries = 2, delayRenderRetries, delayRenderTimeoutInMilliseconds, refForOutline, ...canvasProps }, ref) => {
112
+ const CanvasImageContent = (0, react_1.forwardRef)(({ src, crossOrigin, width, height, fit = 'fill', effects, controls, onError, className, style, id, pauseWhenLoading, maxRetries = 2, delayRenderRetries, delayRenderTimeoutInMilliseconds, refForOutline, ...canvasProps }, ref) => {
113
113
  var _a;
114
114
  const { delayRender, continueRender, cancelRender } = (0, use_delay_render_js_1.useDelayRender)();
115
115
  const { delayPlayback } = (0, use_buffer_state_js_1.useBufferState)();
@@ -187,7 +187,7 @@ const CanvasImageContent = (0, react_1.forwardRef)(({ src, width, height, fit =
187
187
  continued: false,
188
188
  };
189
189
  const attemptLoad = () => {
190
- loadImage({ src: actualSrc, signal: controller.signal })
190
+ loadImage({ src: actualSrc, signal: controller.signal, crossOrigin })
191
191
  .then((image) => {
192
192
  if (cancelled) {
193
193
  return;
@@ -232,6 +232,7 @@ const CanvasImageContent = (0, react_1.forwardRef)(({ src, width, height, fit =
232
232
  actualSrc,
233
233
  cancelRender,
234
234
  continuePendingLoadDelay,
235
+ crossOrigin,
235
236
  delayRender,
236
237
  delayRenderRetries,
237
238
  delayRenderTimeoutInMilliseconds,
@@ -329,10 +330,14 @@ const CanvasImageContent = (0, react_1.forwardRef)(({ src, width, height, fit =
329
330
  return (jsx_runtime_1.jsx("canvas", { ...canvasProps, ref: canvasRef, width: width, height: height, className: className, style: style, id: id }));
330
331
  });
331
332
  CanvasImageContent.displayName = 'CanvasImageContent';
332
- const CanvasImageInner = (0, react_1.forwardRef)(({ src, width, height, fit, effects = [], className, style, id, onError, pauseWhenLoading, maxRetries, delayRenderRetries, delayRenderTimeoutInMilliseconds, durationInFrames, from, trimBefore, freeze, premountFor, postmountFor, styleWhilePremounted, styleWhilePostmounted, hidden, name, showInTimeline, cropLeft, cropRight, cropTop, cropBottom, controls, _remotionInternalDocumentationLink, _remotionInternalCropComponentName, outlineRef, ...canvasProps }, ref) => {
333
+ const CanvasImageInner = (0, react_1.forwardRef)(({ src, crossOrigin, width, height, fit, effects = [], className, style, id, onError, pauseWhenLoading, maxRetries, delayRenderRetries, delayRenderTimeoutInMilliseconds, durationInFrames, from, trimBefore, freeze, premountFor, postmountFor, styleWhilePremounted, styleWhilePostmounted, hidden, name, showInTimeline, cropLeft, cropRight, cropTop, cropBottom, controls, _remotionInternalDocumentationLink, _remotionInternalCropComponentName, outlineRef, ...canvasProps }, ref) => {
333
334
  if (!src) {
334
335
  throw new Error('No "src" prop was passed to <CanvasImage>.');
335
336
  }
337
+ const isMedia = (0, react_1.useMemo)(() => ({
338
+ type: 'image',
339
+ src,
340
+ }), [src]);
336
341
  const memoizedEffectDefinitions = (0, use_memoized_effects_js_1.useMemoizedEffectDefinitions)(effects);
337
342
  const actualRef = (0, react_1.useRef)(null);
338
343
  (0, react_1.useImperativeHandle)(ref, () => {
@@ -356,7 +361,7 @@ const CanvasImageInner = (0, react_1.forwardRef)(({ src, width, height, fit, eff
356
361
  style: premountingStyle,
357
362
  componentName: _remotionInternalCropComponentName !== null && _remotionInternalCropComponentName !== void 0 ? _remotionInternalCropComponentName : '<CanvasImage />',
358
363
  });
359
- return (jsx_runtime_1.jsx(freeze_js_1.Freeze, { frame: freezeFrame, active: isPremountingOrPostmounting, children: jsx_runtime_1.jsx(Sequence_js_1.Sequence, { layout: "none", from: from !== null && from !== void 0 ? from : 0, trimBefore: trimBefore, durationInFrames: durationInFrames !== null && durationInFrames !== void 0 ? durationInFrames : Infinity, freeze: freeze, hidden: hidden, showInTimeline: showInTimeline !== null && showInTimeline !== void 0 ? showInTimeline : true, name: name !== null && name !== void 0 ? name : '<CanvasImage>', _remotionInternalDocumentationLink: _remotionInternalDocumentationLink !== null && _remotionInternalDocumentationLink !== void 0 ? _remotionInternalDocumentationLink : 'https://www.remotion.dev/docs/canvasimage', controls: controls, _remotionInternalEffects: memoizedEffectDefinitions, _remotionInternalIsMedia: { type: 'image', src }, _remotionInternalPremountDisplay: effectivePremountFor || null, _remotionInternalPostmountDisplay: effectivePostmountFor || null, _remotionInternalIsPremounting: premountingActive, _remotionInternalIsPostmounting: postmountingActive, outlineRef: outlineRef !== null && outlineRef !== void 0 ? outlineRef : actualRef, children: jsx_runtime_1.jsx(CanvasImageContent, { ref: actualRef, src: src, width: width, height: height, fit: fit, effects: effects, controls: controls, className: className, style: croppedStyle !== null && croppedStyle !== void 0 ? croppedStyle : undefined, id: id, onError: onError, pauseWhenLoading: pauseWhenLoading, maxRetries: maxRetries, delayRenderRetries: delayRenderRetries, delayRenderTimeoutInMilliseconds: delayRenderTimeoutInMilliseconds, refForOutline: outlineRef !== null && outlineRef !== void 0 ? outlineRef : null, ...canvasProps }) }) }));
364
+ return (jsx_runtime_1.jsx(freeze_js_1.Freeze, { frame: freezeFrame, active: isPremountingOrPostmounting, children: jsx_runtime_1.jsx(Sequence_js_1.Sequence, { layout: "none", from: from !== null && from !== void 0 ? from : 0, trimBefore: trimBefore, durationInFrames: durationInFrames !== null && durationInFrames !== void 0 ? durationInFrames : Infinity, freeze: freeze, hidden: hidden, showInTimeline: showInTimeline !== null && showInTimeline !== void 0 ? showInTimeline : true, name: name !== null && name !== void 0 ? name : '<CanvasImage>', _remotionInternalDocumentationLink: _remotionInternalDocumentationLink !== null && _remotionInternalDocumentationLink !== void 0 ? _remotionInternalDocumentationLink : 'https://www.remotion.dev/docs/canvasimage', controls: controls, _remotionInternalEffects: memoizedEffectDefinitions, _remotionInternalIsMedia: isMedia, _remotionInternalPremountDisplay: effectivePremountFor || null, _remotionInternalPostmountDisplay: effectivePostmountFor || null, _remotionInternalIsPremounting: premountingActive, _remotionInternalIsPostmounting: postmountingActive, outlineRef: outlineRef !== null && outlineRef !== void 0 ? outlineRef : actualRef, children: jsx_runtime_1.jsx(CanvasImageContent, { ref: actualRef, src: src, crossOrigin: crossOrigin, width: width, height: height, fit: fit, effects: effects, controls: controls, className: className, style: croppedStyle !== null && croppedStyle !== void 0 ? croppedStyle : undefined, id: id, onError: onError, pauseWhenLoading: pauseWhenLoading, maxRetries: maxRetries, delayRenderRetries: delayRenderRetries, delayRenderTimeoutInMilliseconds: delayRenderTimeoutInMilliseconds, refForOutline: outlineRef !== null && outlineRef !== void 0 ? outlineRef : null, ...canvasProps }) }) }));
360
365
  });
361
366
  /*
362
367
  * @description Renders a static image to a `<canvas>` and applies Remotion effects.
@@ -6,6 +6,7 @@ type CanvasImageSequenceProps = InteractiveBaseProps & InteractiveCropProps & In
6
6
  export type CanvasImageCanvasProps = Omit<React.CanvasHTMLAttributes<HTMLCanvasElement>, 'children' | 'height' | 'onError' | 'width'>;
7
7
  export type CanvasImageProps = CanvasImageSequenceProps & CanvasImageCanvasProps & {
8
8
  readonly src: string;
9
+ readonly crossOrigin?: React.ImgHTMLAttributes<HTMLImageElement>['crossOrigin'];
9
10
  readonly width?: number;
10
11
  readonly height?: number;
11
12
  readonly fit?: ImageFit;
@@ -30,7 +30,7 @@ const delayRenderInternal = ({ scope, environment, label, options, }) => {
30
30
  scope.remotion_delayRenderHandles.push(handle);
31
31
  const called = (_b = (_a = Error().stack) === null || _a === void 0 ? void 0 : _a.replace(/^Error/g, '')) !== null && _b !== void 0 ? _b : '';
32
32
  if (environment.isRendering) {
33
- const timeoutToUse = ((_d = (_c = options === null || options === void 0 ? void 0 : options.timeoutInMilliseconds) !== null && _c !== void 0 ? _c : scope.remotion_puppeteerTimeout) !== null && _d !== void 0 ? _d : defaultTimeout) - 2000;
33
+ const timeoutToUse = Math.max(0, ((_d = (_c = options === null || options === void 0 ? void 0 : options.timeoutInMilliseconds) !== null && _c !== void 0 ? _c : scope.remotion_puppeteerTimeout) !== null && _d !== void 0 ? _d : defaultTimeout) - 2000);
34
34
  const retriesLeft = ((_e = options === null || options === void 0 ? void 0 : options.retries) !== null && _e !== void 0 ? _e : 0) - (scope.remotion_attempt - 1);
35
35
  scope.remotion_delayRenderTimeouts[handle] = {
36
36
  label: label !== null && label !== void 0 ? label : null,
@@ -5,7 +5,7 @@ import type { AnyCompMetadata, AnyComposition, AudioOrVideoAsset, JsxComponentId
5
5
  import type { DelayRenderScope } from './delay-render.js';
6
6
  import { type TFolder } from './Folder.js';
7
7
  import type { StaticFile } from './get-static-files.js';
8
- import type { AssetFieldSchema, ArrayFieldSchema, ArrayItemFieldSchema, CaptionsFieldSchema, InteractivitySchemaField, InteractivitySchema } from './interactivity-schema.js';
8
+ import type { ArrayFieldSchema, ArrayItemFieldSchema, AssetFieldSchema, CaptionsFieldSchema, InteractivitySchema, InteractivitySchemaField } from './interactivity-schema.js';
9
9
  import type { LogLevel } from './log.js';
10
10
  import type { ProResProfile } from './prores-profile.js';
11
11
  import type { PixelFormat, VideoImageFormat } from './render-types.js';
@@ -135,7 +135,7 @@ export * from './internals.js';
135
135
  export { interpolateColors, type InterpolateColorsOptions, } from './interpolate-colors.js';
136
136
  export { LogLevel } from './log.js';
137
137
  export { Loop } from './loop/index.js';
138
- export { assertValidInterpolateEasingOption, assertValidInterpolatePosterizeOption, EasingFunction, ExtrapolateType, interpolate, InterpolateOutputOption, InterpolateOptions, random, RandomSeed, } from './no-react';
138
+ export { assertValidInterpolateEasingOption, assertValidInterpolatePosterizeOption, EasingFunction, ExtrapolateType, interpolate, InterpolateOptions, InterpolateOutputOption, InterpolateOutputType, random, RandomSeed, } from './no-react';
139
139
  export { prefetch, PrefetchOnProgress } from './prefetch.js';
140
140
  export { registerRoot } from './register-root.js';
141
141
  export type { PixelFormat, VideoImageFormat } from './render-types.js';
@@ -184,4 +184,4 @@ export type _InternalTypes = {
184
184
  TRenderAsset: TRenderAsset;
185
185
  ProResProfile: ProResProfile;
186
186
  };
187
- export type { AnyComposition, AssetFieldSchema, ArrayFieldSchema, ArrayItemFieldSchema, CaptionsFieldSchema, DelayRenderScope, JsxComponentIdentity, LoopDisplay, RuntimeValueSnapshot, RuntimeValueStore, SequenceControls, SequenceRegistrationControls, InteractivitySchemaField, InteractivitySchema, UseBufferState, };
187
+ export type { AnyComposition, ArrayFieldSchema, ArrayItemFieldSchema, AssetFieldSchema, CaptionsFieldSchema, DelayRenderScope, InteractivitySchema, InteractivitySchemaField, JsxComponentIdentity, LoopDisplay, RuntimeValueSnapshot, RuntimeValueStore, SequenceControls, SequenceRegistrationControls, UseBufferState, };
@@ -101,7 +101,7 @@ export type FontWeightFieldSchema = {
101
101
  type: 'font-weight';
102
102
  default: number | string | undefined;
103
103
  description?: string;
104
- keyframable?: false;
104
+ keyframable?: boolean;
105
105
  };
106
106
  export type AssetFieldSchema = {
107
107
  type: 'asset';
@@ -265,7 +265,6 @@ export declare const textSchema: {
265
265
  readonly type: "font-weight";
266
266
  readonly default: 400;
267
267
  readonly description: "Font weight";
268
- readonly keyframable: false;
269
268
  };
270
269
  readonly 'style.fontStyle': {
271
270
  readonly type: "enum";
@@ -79,7 +79,6 @@ exports.textSchema = {
79
79
  type: 'font-weight',
80
80
  default: 400,
81
81
  description: 'Font weight',
82
- keyframable: false,
83
82
  },
84
83
  'style.fontStyle': {
85
84
  type: 'enum',
@@ -654,7 +654,6 @@ export declare const Internals: {
654
654
  readonly type: "font-weight";
655
655
  readonly default: 400;
656
656
  readonly description: "Font weight";
657
- readonly keyframable: false;
658
657
  };
659
658
  readonly 'style.fontStyle': {
660
659
  readonly type: "enum";
@@ -1,5 +1,6 @@
1
1
  export type ExtrapolateType = 'extend' | 'identity' | 'clamp' | 'wrap';
2
2
  export type InterpolateOutputOption = 'linear' | 'perceptual-scale';
3
+ export type InterpolateOutputType = 'font-weight' | 'scale' | 'translate' | 'rotate' | 'transform-origin';
3
4
  /**
4
5
  * @description This function allows you to map a range of values to another with a concise syntax
5
6
  * @see [Documentation](https://www.remotion.dev/docs/interpolate)
@@ -12,6 +13,7 @@ export type InterpolateOptions = Partial<{
12
13
  extrapolateLeft: ExtrapolateType;
13
14
  extrapolateRight: ExtrapolateType;
14
15
  output: InterpolateOutputOption;
16
+ outputType: InterpolateOutputType;
15
17
  posterize: number;
16
18
  }>;
17
19
  type NumericTuple = readonly [number, ...number[]];
@@ -21,6 +23,9 @@ type WidenNumericTuple<T extends readonly number[]> = {
21
23
  export declare function assertValidInterpolateEasingOption(easing: EasingFunction | readonly EasingFunction[] | undefined, inputRangeLength: number): void;
22
24
  export declare function assertValidInterpolatePosterizeOption(posterize: number | undefined): void;
23
25
  export declare function interpolate(input: number, inputRange: readonly number[], outputRange: readonly number[], options?: InterpolateOptions): number;
26
+ export declare function interpolate(input: number, inputRange: readonly number[], outputRange: readonly (number | string)[], options: InterpolateOptions & {
27
+ outputType: 'font-weight';
28
+ }): number;
24
29
  export declare function interpolate(input: number, inputRange: readonly number[], outputRange: readonly string[], options?: InterpolateOptions): string;
25
30
  export declare function interpolate<const Tuple extends NumericTuple>(input: number, inputRange: readonly number[], outputRange: readonly Tuple[], options?: InterpolateOptions): WidenNumericTuple<Tuple>;
26
31
  export declare function interpolate(input: number, inputRange: readonly number[], outputRange: readonly (readonly number[])[], options?: InterpolateOptions): number[];
@@ -254,7 +254,7 @@ const parseAxisRotationValue = (output) => {
254
254
  axisRotation: true,
255
255
  };
256
256
  };
257
- const parseStringInterpolationValue = (output) => {
257
+ const parseStringInterpolationValue = (output, outputType) => {
258
258
  var _a, _b, _c, _d, _e, _f;
259
259
  var _g, _h, _j, _k, _l, _m;
260
260
  if (typeof output === 'number') {
@@ -269,8 +269,20 @@ const parseStringInterpolationValue = (output) => {
269
269
  axisRotation: false,
270
270
  };
271
271
  }
272
+ if (outputType === 'transform-origin') {
273
+ const transformOriginParts = output.trim().split(/\s+/);
274
+ if (transformOriginParts.length < 1 ||
275
+ transformOriginParts.length > 3 ||
276
+ transformOriginParts[0] === '') {
277
+ throw new TypeError(`String outputRange values must contain 1 to 3 components, but got "${output}"`);
278
+ }
279
+ return parseTransformOriginValue(output, transformOriginParts);
280
+ }
272
281
  const axisRotation = parseAxisRotationValue(output);
273
282
  if (axisRotation !== null) {
283
+ if (outputType !== undefined && outputType !== 'rotate') {
284
+ throw new TypeError(`Cannot interpolate "${output}" as ${outputType} because it is a rotate value`);
285
+ }
274
286
  return axisRotation;
275
287
  }
276
288
  const parts = output.trim().split(/\s+/);
@@ -278,6 +290,9 @@ const parseStringInterpolationValue = (output) => {
278
290
  throw new TypeError(`String outputRange values must contain 1 to 3 components, but got "${output}"`);
279
291
  }
280
292
  if (parts.some((part) => transformOriginKeywords.has(part.toLowerCase()))) {
293
+ if (outputType !== undefined) {
294
+ throw new TypeError(`Cannot interpolate "${output}" as ${outputType} because it is a transform-origin value`);
295
+ }
281
296
  return parseTransformOriginValue(output, parts);
282
297
  }
283
298
  const parsed = parts.map((part) => parseStringInterpolationComponent(part, output));
@@ -287,6 +302,9 @@ const parseStringInterpolationValue = (output) => {
287
302
  throw new TypeError(`Cannot interpolate "${output}" because it mixes ${kind} and ${part.kind} values`);
288
303
  }
289
304
  }
305
+ if (outputType !== undefined && outputType !== kind) {
306
+ throw new TypeError(`Cannot interpolate "${output}" as ${outputType} because it is a ${kind} value`);
307
+ }
290
308
  if (kind === 'scale') {
291
309
  const x = parsed[0].value;
292
310
  const y = (_g = (_a = parsed[1]) === null || _a === void 0 ? void 0 : _a.value) !== null && _g !== void 0 ? _g : x;
@@ -486,9 +504,9 @@ const interpolateNumber = ({ input, inputRange, outputRange, options, }) => {
486
504
  }
487
505
  return result;
488
506
  };
489
- const interpolateString = ({ input, inputRange, outputRange, options, }) => {
507
+ const interpolateString = ({ input, inputRange, outputRange, options, outputType, }) => {
490
508
  var _a;
491
- const initiallyParsedOutputRange = outputRange.map(parseStringInterpolationValue);
509
+ const initiallyParsedOutputRange = outputRange.map((output) => parseStringInterpolationValue(output, outputType));
492
510
  const hasAxisRotation = initiallyParsedOutputRange.some((parsed) => parsed.axisRotation);
493
511
  const posterizedInput = (options === null || options === void 0 ? void 0 : options.posterize) === undefined
494
512
  ? input
@@ -589,6 +607,35 @@ const interpolateString = ({ input, inputRange, outputRange, options, }) => {
589
607
  axisRotation: hasAxisRotation,
590
608
  });
591
609
  };
610
+ const interpolateFontWeight = ({ input, inputRange, outputRange, options, }) => {
611
+ const normalizedOutputRange = outputRange.map((output) => {
612
+ if (typeof output === 'string') {
613
+ const lowerCaseOutput = output.toLowerCase();
614
+ if (lowerCaseOutput === 'normal') {
615
+ return 400;
616
+ }
617
+ if (lowerCaseOutput === 'bold') {
618
+ return 700;
619
+ }
620
+ }
621
+ const match = typeof output === 'string' ? cssNumberRegex.exec(output) : null;
622
+ const value = typeof output === 'number'
623
+ ? output
624
+ : match !== null && match[2] === undefined
625
+ ? Number(match[1])
626
+ : Number.NaN;
627
+ if (!Number.isFinite(value) || value < 1 || value > 1000) {
628
+ throw new TypeError(`Cannot interpolate font weight "${output}". Expected "normal", "bold", or a number between 1 and 1000`);
629
+ }
630
+ return value;
631
+ });
632
+ return interpolateNumber({
633
+ input,
634
+ inputRange,
635
+ outputRange: normalizedOutputRange,
636
+ options,
637
+ });
638
+ };
592
639
  const interpolateDiscreteString = ({ input, inputRange, outputRange, options, }) => {
593
640
  if (inputRange.length === 1) {
594
641
  return outputRange[0];
@@ -725,6 +772,17 @@ function assertValidInterpolateOutputOption(output) {
725
772
  }
726
773
  throw new Error(`output must be "linear" or "perceptual-scale", but got ${String(output)}`);
727
774
  }
775
+ function assertValidInterpolateOutputType(outputType) {
776
+ if (outputType === undefined ||
777
+ outputType === 'font-weight' ||
778
+ outputType === 'scale' ||
779
+ outputType === 'translate' ||
780
+ outputType === 'rotate' ||
781
+ outputType === 'transform-origin') {
782
+ return;
783
+ }
784
+ throw new Error(`outputType must be "font-weight", "scale", "translate", "rotate", or "transform-origin", but got ${String(outputType)}`);
785
+ }
728
786
  function interpolate(input, inputRange, outputRange, options) {
729
787
  if (typeof input === 'undefined') {
730
788
  throw new Error('input can not be undefined');
@@ -747,19 +805,41 @@ function interpolate(input, inputRange, outputRange, options) {
747
805
  assertValidInterpolateEasingOption(options === null || options === void 0 ? void 0 : options.easing, inputRange.length);
748
806
  assertValidInterpolatePosterizeOption(options === null || options === void 0 ? void 0 : options.posterize);
749
807
  assertValidInterpolateOutputOption(options === null || options === void 0 ? void 0 : options.output);
808
+ assertValidInterpolateOutputType(options === null || options === void 0 ? void 0 : options.outputType);
750
809
  if (typeof input !== 'number') {
751
810
  throw new TypeError('Cannot interpolate an input which is not a number');
752
811
  }
753
812
  if (!Array.isArray(outputRange)) {
754
813
  throw new Error('outputRange must contain only numbers');
755
814
  }
815
+ const outputType = options === null || options === void 0 ? void 0 : options.outputType;
816
+ if (outputType === 'font-weight') {
817
+ if (!outputRange.every((output) => typeof output === 'number' || typeof output === 'string')) {
818
+ throw new TypeError('Font weight outputRange must contain only numbers or strings');
819
+ }
820
+ return interpolateFontWeight({
821
+ input,
822
+ inputRange,
823
+ outputRange,
824
+ options,
825
+ });
826
+ }
756
827
  const hasStringOutput = outputRange.some((output) => typeof output === 'string');
828
+ if (outputType !== undefined && outputType !== 'scale' && !hasStringOutput) {
829
+ throw new TypeError(`${outputType} outputRange must contain strings with the appropriate CSS units`);
830
+ }
757
831
  if (hasStringOutput) {
758
832
  if (!outputRange.every((output) => typeof output === 'string' || typeof output === 'number')) {
759
833
  throw new TypeError('outputRange must contain only numbers, or supported scale, translate, and rotate strings');
760
834
  }
761
835
  try {
762
- return interpolateString({ input, inputRange, outputRange, options });
836
+ return interpolateString({
837
+ input,
838
+ inputRange,
839
+ outputRange,
840
+ options,
841
+ outputType,
842
+ });
763
843
  }
764
844
  catch (error) {
765
845
  if (!outputRange.every((output) => typeof output === 'string')) {
@@ -767,7 +847,7 @@ function interpolate(input, inputRange, outputRange, options) {
767
847
  }
768
848
  const hasNonNumericString = outputRange.some((output) => {
769
849
  try {
770
- parseStringInterpolationValue(output);
850
+ parseStringInterpolationValue(output, outputType);
771
851
  return false;
772
852
  }
773
853
  catch (parseError) {
@@ -1,7 +1,7 @@
1
1
  export type { ArtifactAsset, AudioOrVideoAsset, InlineAudioAsset, TRenderAsset, } from './CompositionManager';
2
2
  export type { DownloadBehavior } from './download-behavior';
3
3
  export { assertValidInterpolateEasingOption, assertValidInterpolatePosterizeOption, interpolate, } from './interpolate';
4
- export type { EasingFunction, ExtrapolateType, InterpolateOutputOption, InterpolateOptions, } from './interpolate';
4
+ export type { EasingFunction, ExtrapolateType, InterpolateOptions, InterpolateOutputOption, InterpolateOutputType, } from './interpolate';
5
5
  export { random } from './random.js';
6
6
  export type { RandomSeed } from './random.js';
7
7
  export type { VideoConfig } from './video-config';
@@ -64,15 +64,24 @@ function advance({ animation, now, config, }) {
64
64
  }
65
65
  const calculationCache = {};
66
66
  function springCalculation({ frame, fps, config = {}, }) {
67
+ var _a, _b, _c, _d;
67
68
  const from = 0;
68
69
  const to = 1;
70
+ // An explicit `undefined` (e.g. a forwarded optional prop) must not
71
+ // override the defaults, otherwise the physics turn into NaN
72
+ const resolvedConfig = {
73
+ damping: (_a = config.damping) !== null && _a !== void 0 ? _a : defaultSpringConfig.damping,
74
+ mass: (_b = config.mass) !== null && _b !== void 0 ? _b : defaultSpringConfig.mass,
75
+ stiffness: (_c = config.stiffness) !== null && _c !== void 0 ? _c : defaultSpringConfig.stiffness,
76
+ overshootClamping: (_d = config.overshootClamping) !== null && _d !== void 0 ? _d : defaultSpringConfig.overshootClamping,
77
+ };
69
78
  const cacheKey = [
70
79
  frame,
71
80
  fps,
72
- config.damping,
73
- config.mass,
74
- config.overshootClamping,
75
- config.stiffness,
81
+ resolvedConfig.damping,
82
+ resolvedConfig.mass,
83
+ resolvedConfig.overshootClamping,
84
+ resolvedConfig.stiffness,
76
85
  ].join('-');
77
86
  if (calculationCache[cacheKey]) {
78
87
  return calculationCache[cacheKey];
@@ -91,20 +100,14 @@ function springCalculation({ frame, fps, config = {}, }) {
91
100
  animation = advance({
92
101
  animation,
93
102
  now: time,
94
- config: {
95
- ...defaultSpringConfig,
96
- ...config,
97
- },
103
+ config: resolvedConfig,
98
104
  });
99
105
  }
100
106
  if (unevenRest > 0) {
101
107
  animation = advance({
102
108
  animation,
103
109
  now: (frameClamped / fps) * 1000,
104
- config: {
105
- ...defaultSpringConfig,
106
- ...config,
107
- },
110
+ config: resolvedConfig,
108
111
  });
109
112
  }
110
113
  calculationCache[cacheKey] = animation;
@@ -3,4 +3,4 @@
3
3
  * @see [Documentation](https://remotion.dev/docs/version)
4
4
  * @returns {string} The current version of the remotion package
5
5
  */
6
- export declare const VERSION = "4.0.525";
6
+ export declare const VERSION = "4.0.527";
@@ -7,4 +7,4 @@ exports.VERSION = void 0;
7
7
  * @see [Documentation](https://remotion.dev/docs/version)
8
8
  * @returns {string} The current version of the remotion package
9
9
  */
10
- exports.VERSION = '4.0.525';
10
+ exports.VERSION = '4.0.527';