remotion 4.0.467 → 4.0.469

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.
@@ -70,6 +70,7 @@ export type TSequence = {
70
70
  premountDisplay: number | null;
71
71
  postmountDisplay: number | null;
72
72
  controls: SequenceControls | null;
73
+ refForOutline: React.RefObject<HTMLElement | null> | null;
73
74
  effects: readonly EffectDefinition<unknown>[];
74
75
  } & EnhancedTSequenceData;
75
76
  export type AudioOrVideoAsset = {
package/dist/cjs/Img.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
+ import type { EffectsProp } from './effects/effect-types.js';
2
3
  import type { SequenceProps } from './Sequence.js';
3
- export declare function truncateSrcForLabel(src: string): string;
4
4
  type NativeImgProps = Omit<React.DetailedHTMLProps<React.ImgHTMLAttributes<HTMLImageElement>, HTMLImageElement>, 'src'>;
5
5
  export type ImgProps = NativeImgProps & {
6
6
  readonly maxRetries?: number;
@@ -9,6 +9,7 @@ export type ImgProps = NativeImgProps & {
9
9
  readonly delayRenderTimeoutInMilliseconds?: number;
10
10
  readonly onImageFrame?: (imageElement: HTMLImageElement) => void;
11
11
  readonly src: string;
12
+ readonly effects?: EffectsProp;
12
13
  readonly showInTimeline?: boolean;
13
14
  readonly name?: string;
14
15
  /**
@@ -16,6 +17,37 @@ export type ImgProps = NativeImgProps & {
16
17
  */
17
18
  readonly stack?: string;
18
19
  } & Pick<SequenceProps, 'durationInFrames' | 'from' | 'hidden'>;
20
+ export declare const imgSchema: {
21
+ readonly hidden: import("./sequence-field-schema.js").SequenceFieldSchema;
22
+ readonly 'style.translate': {
23
+ readonly type: "translate";
24
+ readonly step: 1;
25
+ readonly default: "0px 0px";
26
+ readonly description: "Offset";
27
+ };
28
+ readonly 'style.scale': {
29
+ readonly type: "number";
30
+ readonly min: 0.05;
31
+ readonly max: 100;
32
+ readonly step: 0.01;
33
+ readonly default: 1;
34
+ readonly description: "Scale";
35
+ };
36
+ readonly 'style.rotate': {
37
+ readonly type: "rotation";
38
+ readonly step: 1;
39
+ readonly default: "0deg";
40
+ readonly description: "Rotation";
41
+ };
42
+ readonly 'style.opacity': {
43
+ readonly type: "number";
44
+ readonly min: 0;
45
+ readonly max: 1;
46
+ readonly step: 0.01;
47
+ readonly default: 1;
48
+ readonly description: "Opacity";
49
+ };
50
+ };
19
51
  export declare const Img: React.ComponentType<NativeImgProps & {
20
52
  readonly maxRetries?: number;
21
53
  readonly pauseWhenLoading?: boolean;
@@ -23,6 +55,7 @@ export declare const Img: React.ComponentType<NativeImgProps & {
23
55
  readonly delayRenderTimeoutInMilliseconds?: number;
24
56
  readonly onImageFrame?: (imageElement: HTMLImageElement) => void;
25
57
  readonly src: string;
58
+ readonly effects?: EffectsProp;
26
59
  readonly showInTimeline?: boolean;
27
60
  readonly name?: string;
28
61
  /**
package/dist/cjs/Img.js CHANGED
@@ -1,15 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Img = void 0;
4
- exports.truncateSrcForLabel = truncateSrcForLabel;
3
+ exports.Img = exports.imgSchema = void 0;
5
4
  const jsx_runtime_1 = require("react/jsx-runtime");
6
5
  const react_1 = require("react");
6
+ const index_js_1 = require("./canvas-image/index.js");
7
7
  const enable_sequence_stack_traces_js_1 = require("./enable-sequence-stack-traces.js");
8
8
  const get_cross_origin_value_js_1 = require("./get-cross-origin-value.js");
9
9
  const prefetch_js_1 = require("./prefetch.js");
10
10
  const sequence_field_schema_js_1 = require("./sequence-field-schema.js");
11
11
  const Sequence_js_1 = require("./Sequence.js");
12
12
  const SequenceContext_js_1 = require("./SequenceContext.js");
13
+ const truncate_src_for_label_js_1 = require("./truncate-src-for-label.js");
13
14
  const use_buffer_state_js_1 = require("./use-buffer-state.js");
14
15
  const use_delay_render_js_1 = require("./use-delay-render.js");
15
16
  const use_remotion_environment_js_1 = require("./use-remotion-environment.js");
@@ -17,14 +18,6 @@ const wrap_in_schema_js_1 = require("./wrap-in-schema.js");
17
18
  function exponentialBackoff(errorCount) {
18
19
  return 1000 * 2 ** (errorCount - 1);
19
20
  }
20
- // Data URLs like the ones from canvas.toDataURL() can be many megabytes, which makes the delayRender() label
21
- // unreadable and bloats log output
22
- function truncateSrcForLabel(src) {
23
- if (src.startsWith('data:') && src.length > 100) {
24
- return src.slice(0, 60) + '...[' + src.length + ' chars total]';
25
- }
26
- return src;
27
- }
28
21
  const ImgContent = ({ onError, maxRetries = 2, src, pauseWhenLoading, delayRenderRetries, delayRenderTimeoutInMilliseconds, onImageFrame, crossOrigin, decoding, ref, ...props }) => {
29
22
  const imageRef = (0, react_1.useRef)(null);
30
23
  const errors = (0, react_1.useRef)({});
@@ -74,13 +67,13 @@ const ImgContent = ({ onError, maxRetries = 2, src, pauseWhenLoading, delayRende
74
67
  if (((_g = errors.current[(_f = imageRef.current) === null || _f === void 0 ? void 0 : _f.src]) !== null && _g !== void 0 ? _g : 0) <= maxRetries) {
75
68
  const backoff = exponentialBackoff((_j = errors.current[(_h = imageRef.current) === null || _h === void 0 ? void 0 : _h.src]) !== null && _j !== void 0 ? _j : 0);
76
69
  // eslint-disable-next-line no-console
77
- console.warn(`Could not load image with source ${truncateSrcForLabel((_k = imageRef.current) === null || _k === void 0 ? void 0 : _k.src)}, retrying again in ${backoff}ms`);
70
+ console.warn(`Could not load image with source ${(0, truncate_src_for_label_js_1.truncateSrcForLabel)((_k = imageRef.current) === null || _k === void 0 ? void 0 : _k.src)}, retrying again in ${backoff}ms`);
78
71
  retryIn(backoff);
79
72
  return;
80
73
  }
81
74
  try {
82
75
  cancelRender('Error loading image with src: ' +
83
- truncateSrcForLabel((_l = imageRef.current) === null || _l === void 0 ? void 0 : _l.src));
76
+ (0, truncate_src_for_label_js_1.truncateSrcForLabel)((_l = imageRef.current) === null || _l === void 0 ? void 0 : _l.src));
84
77
  }
85
78
  catch (_m) {
86
79
  // cancelRender() intentionally throws after storing the error in scope.
@@ -103,7 +96,7 @@ const ImgContent = ({ onError, maxRetries = 2, src, pauseWhenLoading, delayRende
103
96
  if (!current) {
104
97
  return;
105
98
  }
106
- const newHandle = delayRender('Loading <Img> with src=' + truncateSrcForLabel(actualSrc), {
99
+ const newHandle = delayRender('Loading <Img> with src=' + (0, truncate_src_for_label_js_1.truncateSrcForLabel)(actualSrc), {
107
100
  retries: delayRenderRetries !== null && delayRenderRetries !== void 0 ? delayRenderRetries : undefined,
108
101
  timeoutInMilliseconds: delayRenderTimeoutInMilliseconds !== null && delayRenderTimeoutInMilliseconds !== void 0 ? delayRenderTimeoutInMilliseconds : undefined,
109
102
  });
@@ -121,7 +114,7 @@ const ImgContent = ({ onError, maxRetries = 2, src, pauseWhenLoading, delayRende
121
114
  if (((_b = errors.current[(_a = imageRef.current) === null || _a === void 0 ? void 0 : _a.src]) !== null && _b !== void 0 ? _b : 0) > 0) {
122
115
  delete errors.current[(_c = imageRef.current) === null || _c === void 0 ? void 0 : _c.src];
123
116
  // eslint-disable-next-line no-console
124
- console.info(`Retry successful - ${truncateSrcForLabel((_d = imageRef.current) === null || _d === void 0 ? void 0 : _d.src)} is now loaded`);
117
+ console.info(`Retry successful - ${(0, truncate_src_for_label_js_1.truncateSrcForLabel)((_d = imageRef.current) === null || _d === void 0 ? void 0 : _d.src)} is now loaded`);
125
118
  }
126
119
  if (current) {
127
120
  onImageFrame === null || onImageFrame === void 0 ? void 0 : onImageFrame(current);
@@ -181,19 +174,79 @@ const ImgContent = ({ onError, maxRetries = 2, src, pauseWhenLoading, delayRende
181
174
  // src gets set once we've loaded and decoded the image.
182
175
  return ((0, jsx_runtime_1.jsx)("img", { ...props, ref: imageRef, crossOrigin: crossOriginValue, onError: didGetError, decoding: isRendering ? 'sync' : decoding }));
183
176
  };
184
- const ImgInner = ({ hidden, name, stack, showInTimeline, src, from, durationInFrames, _experimentalControls: controls, ...props }) => {
177
+ const NativeImgInner = ({ hidden, name, stack, showInTimeline, src, from, durationInFrames, _experimentalControls: controls, ...props }) => {
185
178
  if (!src) {
186
179
  throw new Error('No "src" prop was passed to <Img>.');
187
180
  }
188
181
  return ((0, jsx_runtime_1.jsx)(Sequence_js_1.Sequence, { layout: "none", from: from !== null && from !== void 0 ? from : 0, durationInFrames: durationInFrames !== null && durationInFrames !== void 0 ? durationInFrames : Infinity, _remotionInternalStack: stack, _remotionInternalDocumentationLink: name === undefined ? 'https://www.remotion.dev/docs/img' : undefined, _remotionInternalIsMedia: { type: 'image', src }, name: name !== null && name !== void 0 ? name : '<Img>', _experimentalControls: controls, showInTimeline: showInTimeline !== null && showInTimeline !== void 0 ? showInTimeline : true, hidden: hidden, children: (0, jsx_runtime_1.jsx)(ImgContent, { src: src, ...props }) }));
189
182
  };
190
- const imgSchema = {
183
+ const CanvasImageWithPrivateProps = index_js_1.CanvasImage;
184
+ exports.imgSchema = {
191
185
  ...sequence_field_schema_js_1.sequenceVisualStyleSchema,
192
186
  hidden: sequence_field_schema_js_1.hiddenField,
193
187
  };
188
+ const imgCanvasFallbackIncompatibleProps = new Set([
189
+ 'alt',
190
+ 'crossOrigin',
191
+ 'decoding',
192
+ 'fetchPriority',
193
+ 'loading',
194
+ 'onError',
195
+ 'onImageFrame',
196
+ 'onLoad',
197
+ 'sizes',
198
+ 'srcSet',
199
+ 'useMap',
200
+ ]);
201
+ const getIncompatiblePropNames = (props) => Object.keys(props).filter((key) => props[key] !== undefined && imgCanvasFallbackIncompatibleProps.has(key));
202
+ const formatPropList = (props) => {
203
+ return props.map((prop) => `"${prop}"`).join(', ');
204
+ };
205
+ const validateCanvasImageFallbackProps = ({ props, ref, width, height, }) => {
206
+ if (typeof width === 'string' || typeof height === 'string') {
207
+ throw new Error('The "width" and "height" props must be numbers on <Img> when effects are passed, because <Img> renders a <CanvasImage>. Use numeric props or CSS dimensions in "style".');
208
+ }
209
+ const conflictingProps = getIncompatiblePropNames(props);
210
+ if (ref !== null && ref !== undefined) {
211
+ conflictingProps.unshift('ref');
212
+ }
213
+ if (conflictingProps.length === 0) {
214
+ return;
215
+ }
216
+ throw new Error(`The ${formatPropList(conflictingProps)} prop${conflictingProps.length === 1 ? '' : 's'} cannot be used on <Img> when effects are passed, because <Img> renders a <canvas> instead of a native <img>. Remove ${conflictingProps.length === 1 ? 'this prop' : 'these props'}.`);
217
+ };
218
+ const getFitFromObjectFit = (style) => {
219
+ const objectFit = style === null || style === void 0 ? void 0 : style.objectFit;
220
+ if (objectFit === 'fill' ||
221
+ objectFit === 'contain' ||
222
+ objectFit === 'cover') {
223
+ return objectFit;
224
+ }
225
+ return undefined;
226
+ };
227
+ const ImgInner = ({ effects = [], ref, hidden, name, stack, showInTimeline, src, from, durationInFrames, _experimentalControls: controls, width, height, className, style, id, pauseWhenLoading, maxRetries, delayRenderRetries, delayRenderTimeoutInMilliseconds, ...props }) => {
228
+ var _a;
229
+ if (effects.length === 0) {
230
+ return ((0, jsx_runtime_1.jsx)(NativeImgInner, { ...props, ref: ref, hidden: hidden, name: name, stack: stack, showInTimeline: showInTimeline, src: src, from: from, durationInFrames: durationInFrames, _experimentalControls: controls, width: width, height: height, className: className, style: style, id: id, pauseWhenLoading: pauseWhenLoading, maxRetries: maxRetries, delayRenderRetries: delayRenderRetries, delayRenderTimeoutInMilliseconds: delayRenderTimeoutInMilliseconds }));
231
+ }
232
+ if (!src) {
233
+ throw new Error('No "src" prop was passed to <Img>.');
234
+ }
235
+ validateCanvasImageFallbackProps({
236
+ props,
237
+ ref,
238
+ width,
239
+ height,
240
+ });
241
+ const canvasWidth = typeof width === 'number' ? width : undefined;
242
+ const canvasHeight = typeof height === 'number' ? height : undefined;
243
+ const canvasProps = props;
244
+ const canvasFit = (_a = getFitFromObjectFit(style)) !== null && _a !== void 0 ? _a : 'fill';
245
+ return ((0, jsx_runtime_1.jsx)(CanvasImageWithPrivateProps, { src: src, width: canvasWidth, height: canvasHeight, fit: canvasFit, effects: effects, className: className, style: style, id: id, pauseWhenLoading: pauseWhenLoading, maxRetries: maxRetries, delayRenderRetries: delayRenderRetries, delayRenderTimeoutInMilliseconds: delayRenderTimeoutInMilliseconds, from: from, durationInFrames: durationInFrames, hidden: hidden, name: name !== null && name !== void 0 ? name : '<Img>', showInTimeline: showInTimeline, stack: stack, _remotionInternalDocumentationLink: name === undefined ? 'https://www.remotion.dev/docs/img' : undefined, _experimentalControls: controls, ...canvasProps }));
246
+ };
194
247
  /*
195
248
  * @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.
196
249
  * @see [Documentation](https://remotion.dev/docs/img)
197
250
  */
198
- exports.Img = (0, wrap_in_schema_js_1.wrapInSchema)(ImgInner, imgSchema);
251
+ exports.Img = (0, wrap_in_schema_js_1.wrapInSchema)(ImgInner, exports.imgSchema);
199
252
  (0, enable_sequence_stack_traces_js_1.addSequenceStackTraces)(exports.Img);
@@ -62,6 +62,10 @@ export type SequencePropsWithoutDuration = {
62
62
  type: 'image';
63
63
  src: string;
64
64
  };
65
+ /**
66
+ * @deprecated For internal use only.
67
+ */
68
+ readonly _remotionInternalRefForOutline?: React.RefObject<HTMLElement | null> | null;
65
69
  } & LayoutAndStyle;
66
70
  export type SequenceProps = {
67
71
  readonly durationInFrames?: number;
@@ -4,7 +4,6 @@ exports.Sequence = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  /* eslint-disable @typescript-eslint/no-use-before-define */
6
6
  const react_1 = require("react");
7
- const react_2 = require("react");
8
7
  const AbsoluteFill_js_1 = require("./AbsoluteFill.js");
9
8
  const freeze_js_1 = require("./freeze.js");
10
9
  const nonce_js_1 = require("./nonce.js");
@@ -18,7 +17,7 @@ const use_remotion_environment_js_1 = require("./use-remotion-environment.js");
18
17
  const use_video_config_js_1 = require("./use-video-config.js");
19
18
  const v5_flag_js_1 = require("./v5-flag.js");
20
19
  const wrap_in_schema_js_1 = require("./wrap-in-schema.js");
21
- const RegularSequenceRefForwardingFunction = ({ from = 0, durationInFrames = Infinity, children, name, height, width, showInTimeline = true, hidden = false, _experimentalControls: controls, _remotionInternalEffects, _remotionInternalLoopDisplay: loopDisplay, _remotionInternalStack: stack, _remotionInternalDocumentationLink: documentationLink, _remotionInternalPremountDisplay: premountDisplay, _remotionInternalPostmountDisplay: postmountDisplay, _remotionInternalIsMedia: isMedia, ...other }, ref) => {
20
+ const RegularSequenceRefForwardingFunction = ({ from = 0, durationInFrames = Infinity, children, name, height, width, showInTimeline = true, hidden = false, _experimentalControls: controls, _remotionInternalEffects, _remotionInternalLoopDisplay: loopDisplay, _remotionInternalStack: stack, _remotionInternalDocumentationLink: documentationLink, _remotionInternalPremountDisplay: premountDisplay, _remotionInternalPostmountDisplay: postmountDisplay, _remotionInternalIsMedia: isMedia, _remotionInternalRefForOutline: refForOutline, ...other }, ref) => {
22
21
  var _a;
23
22
  const { layout = 'absolute-fill' } = other;
24
23
  const [id] = (0, react_1.useState)(() => String(Math.random()));
@@ -66,11 +65,34 @@ const RegularSequenceRefForwardingFunction = ({ from = 0, durationInFrames = Inf
66
65
  return ((parentSequence === null || parentSequence === void 0 ? void 0 : parentSequence.postmounting) ||
67
66
  Boolean(other._remotionInternalIsPostmounting));
68
67
  }, [other._remotionInternalIsPostmounting, parentSequence === null || parentSequence === void 0 ? void 0 : parentSequence.postmounting]);
68
+ // `cumulatedNegativeFrom` answers: "How many frames of this media have
69
+ // already elapsed before the first visible frame of this sequence?"
70
+ //
71
+ // This is intentionally based on the effective sequence start, not on adding
72
+ // all negative `from` values. See the asset-calculation tests for:
73
+ // - "Should calculate startFrom correctly with negative offset (Html5Audio)"
74
+ // - "same as above, but with <Sequence from={0}> inbetween"
75
+ // - "same as above, but a positive child offset cancels part of the negative parent offset"
76
+ //
77
+ // In particular, <Sequence from={-20}><Sequence from={10}> should have a
78
+ // 10-frame pre-roll, because the positive child offset cancels part of the
79
+ // negative parent offset. But <Sequence from={10}><Sequence from={-5}>
80
+ // should still trim 5 frames from the media once the parent starts.
81
+ const currentSequenceStart = cumulatedFrom + from;
82
+ const parentSequenceStart = parentSequence
83
+ ? parentSequence.cumulatedFrom + parentSequence.relativeFrom
84
+ : 0;
85
+ const parentFirstFrame = parentSequence
86
+ ? parentSequenceStart - parentSequence.cumulatedNegativeFrom
87
+ : 0;
88
+ const firstFrame = Math.max(0, parentFirstFrame, currentSequenceStart);
89
+ const cumulatedNegativeFrom = currentSequenceStart - firstFrame;
69
90
  const contextValue = (0, react_1.useMemo)(() => {
70
91
  var _a, _b, _c;
71
92
  return {
72
93
  cumulatedFrom,
73
94
  relativeFrom: from,
95
+ cumulatedNegativeFrom,
74
96
  durationInFrames: actualDurationInFrames,
75
97
  parentFrom: (_a = parentSequence === null || parentSequence === void 0 ? void 0 : parentSequence.relativeFrom) !== null && _a !== void 0 ? _a : 0,
76
98
  id,
@@ -93,6 +115,7 @@ const RegularSequenceRefForwardingFunction = ({ from = 0, durationInFrames = Inf
93
115
  postmounting,
94
116
  premountDisplay,
95
117
  postmountDisplay,
118
+ cumulatedNegativeFrom,
96
119
  ]);
97
120
  const timelineClipName = (0, react_1.useMemo)(() => {
98
121
  return name !== null && name !== void 0 ? name : '';
@@ -102,7 +125,7 @@ const RegularSequenceRefForwardingFunction = ({ from = 0, durationInFrames = Inf
102
125
  const inheritedStack = (_a = other === null || other === void 0 ? void 0 : other.stack) !== null && _a !== void 0 ? _a : null;
103
126
  // Our assumption: Stack doesnt' change. After we symbolicate we assign it a nodePath
104
127
  // and if it changes, it would lead to-remounting of the sequence.
105
- const stackRef = (0, react_2.useRef)(null);
128
+ const stackRef = (0, react_1.useRef)(null);
106
129
  stackRef.current = stack !== null && stack !== void 0 ? stack : inheritedStack;
107
130
  (0, react_1.useEffect)(() => {
108
131
  var _a, _b, _c;
@@ -129,6 +152,7 @@ const RegularSequenceRefForwardingFunction = ({ from = 0, durationInFrames = Inf
129
152
  showInTimeline,
130
153
  src: isMedia.src,
131
154
  getStack: () => stackRef.current,
155
+ refForOutline: refForOutline !== null && refForOutline !== void 0 ? refForOutline : null,
132
156
  });
133
157
  }
134
158
  else {
@@ -154,6 +178,7 @@ const RegularSequenceRefForwardingFunction = ({ from = 0, durationInFrames = Inf
154
178
  getStack: () => stackRef.current,
155
179
  startMediaFrom: isMedia.data.startMediaFrom,
156
180
  volume: isMedia.data.volumes,
181
+ refForOutline: refForOutline !== null && refForOutline !== void 0 ? refForOutline : null,
157
182
  });
158
183
  }
159
184
  return () => {
@@ -177,6 +202,7 @@ const RegularSequenceRefForwardingFunction = ({ from = 0, durationInFrames = Inf
177
202
  postmountDisplay: postmountDisplay !== null && postmountDisplay !== void 0 ? postmountDisplay : null,
178
203
  controls: controls !== null && controls !== void 0 ? controls : null,
179
204
  effects: _remotionInternalEffects !== null && _remotionInternalEffects !== void 0 ? _remotionInternalEffects : [],
205
+ refForOutline: refForOutline !== null && refForOutline !== void 0 ? refForOutline : null,
180
206
  });
181
207
  return () => {
182
208
  unregisterSequence(id);
@@ -202,6 +228,7 @@ const RegularSequenceRefForwardingFunction = ({ from = 0, durationInFrames = Inf
202
228
  _remotionInternalEffects,
203
229
  isMedia,
204
230
  resolvedDocumentationLink,
231
+ refForOutline,
205
232
  ]);
206
233
  // Ceil to support floats
207
234
  // https://github.com/remotion-dev/remotion/issues/2958
@@ -1,6 +1,7 @@
1
1
  export declare const SequenceContext: import("react").Context<SequenceContextType | null>;
2
2
  export type SequenceContextType = {
3
3
  cumulatedFrom: number;
4
+ cumulatedNegativeFrom: number;
4
5
  relativeFrom: number;
5
6
  parentFrom: number;
6
7
  durationInFrames: number;
@@ -135,6 +135,7 @@ const AudioForDevelopmentForwardRefFunction = (props, ref) => {
135
135
  postmountDisplay: (_b = sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.postmountDisplay) !== null && _b !== void 0 ? _b : null,
136
136
  loopDisplay: undefined,
137
137
  documentationLink: name === undefined ? 'https://www.remotion.dev/docs/html5-audio' : null,
138
+ refForOutline: null,
138
139
  });
139
140
  // putting playback before useVolume
140
141
  // because volume looks at playbackrate
@@ -65,7 +65,7 @@ const AudioForRenderingRefForwardingFunction = (props, ref) => {
65
65
  mediaFrame: frame,
66
66
  playbackRate: (_a = props.playbackRate) !== null && _a !== void 0 ? _a : 1,
67
67
  toneFrequency: toneFrequency !== null && toneFrequency !== void 0 ? toneFrequency : 1,
68
- audioStartFrame: Math.max(0, -((_b = sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.relativeFrom) !== null && _b !== void 0 ? _b : 0)),
68
+ audioStartFrame: Math.max(0, -((_b = sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.cumulatedNegativeFrom) !== null && _b !== void 0 ? _b : 0)),
69
69
  audioStreamIndex: audioStreamIndex !== null && audioStreamIndex !== void 0 ? audioStreamIndex : 0,
70
70
  });
71
71
  return () => unregisterRenderAsset(id);
@@ -82,7 +82,7 @@ const AudioForRenderingRefForwardingFunction = (props, ref) => {
82
82
  playbackRate,
83
83
  props.playbackRate,
84
84
  toneFrequency,
85
- sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.relativeFrom,
85
+ sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.cumulatedNegativeFrom,
86
86
  audioStreamIndex,
87
87
  ]);
88
88
  const { src } = props;
@@ -8,8 +8,7 @@ const use_current_frame_js_1 = require("../use-current-frame.js");
8
8
  const useMediaStartsAt = () => {
9
9
  var _a;
10
10
  const parentSequence = (0, react_1.useContext)(SequenceContext_js_1.SequenceContext);
11
- const startsAt = Math.min(0, (_a = parentSequence === null || parentSequence === void 0 ? void 0 : parentSequence.relativeFrom) !== null && _a !== void 0 ? _a : 0);
12
- return startsAt;
11
+ return (_a = parentSequence === null || parentSequence === void 0 ? void 0 : parentSequence.cumulatedNegativeFrom) !== null && _a !== void 0 ? _a : 0;
13
12
  };
14
13
  exports.useMediaStartsAt = useMediaStartsAt;
15
14
  /**
@@ -1,7 +1,49 @@
1
1
  import type { EffectsProp } from '../effects/effect-types.js';
2
+ import type { CanvasImageCanvasProps } from './props.js';
3
+ export declare const canvasImageSchema: {
4
+ readonly hidden: import("../sequence-field-schema.js").SequenceFieldSchema;
5
+ readonly 'style.translate': {
6
+ readonly type: "translate";
7
+ readonly step: 1;
8
+ readonly default: "0px 0px";
9
+ readonly description: "Offset";
10
+ };
11
+ readonly 'style.scale': {
12
+ readonly type: "number";
13
+ readonly min: 0.05;
14
+ readonly max: 100;
15
+ readonly step: 0.01;
16
+ readonly default: 1;
17
+ readonly description: "Scale";
18
+ };
19
+ readonly 'style.rotate': {
20
+ readonly type: "rotation";
21
+ readonly step: 1;
22
+ readonly default: "0deg";
23
+ readonly description: "Rotation";
24
+ };
25
+ readonly 'style.opacity': {
26
+ readonly type: "number";
27
+ readonly min: 0;
28
+ readonly max: 1;
29
+ readonly step: 0.01;
30
+ readonly default: 1;
31
+ readonly description: "Opacity";
32
+ };
33
+ readonly fit: {
34
+ readonly type: "enum";
35
+ readonly default: "fill";
36
+ readonly description: "Fit";
37
+ readonly variants: {
38
+ readonly fill: {};
39
+ readonly contain: {};
40
+ readonly cover: {};
41
+ };
42
+ };
43
+ };
2
44
  export declare const CanvasImage: import("react").ComponentType<Pick<import("../Sequence.js").SequenceProps, "hidden" | "name" | "durationInFrames" | "from" | "showInTimeline"> & {
3
45
  readonly stack?: string;
4
- } & {
46
+ } & CanvasImageCanvasProps & {
5
47
  readonly src: string;
6
48
  readonly width?: number;
7
49
  readonly height?: number;
@@ -15,4 +57,5 @@ export declare const CanvasImage: import("react").ComponentType<Pick<import("../
15
57
  readonly maxRetries?: number;
16
58
  readonly delayRenderRetries?: number;
17
59
  readonly delayRenderTimeoutInMilliseconds?: number;
60
+ readonly _remotionInternalDocumentationLink?: string;
18
61
  } & import("react").RefAttributes<HTMLCanvasElement>>;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CanvasImage = void 0;
3
+ exports.CanvasImage = exports.canvasImageSchema = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const calculate_image_fit_js_1 = require("../calculate-image-fit.js");
@@ -8,15 +8,15 @@ const run_effect_chain_js_1 = require("../effects/run-effect-chain.js");
8
8
  const use_effect_chain_state_js_1 = require("../effects/use-effect-chain-state.js");
9
9
  const use_memoized_effects_js_1 = require("../effects/use-memoized-effects.js");
10
10
  const enable_sequence_stack_traces_js_1 = require("../enable-sequence-stack-traces.js");
11
- const Img_js_1 = require("../Img.js");
12
11
  const prefetch_js_1 = require("../prefetch.js");
13
12
  const sequence_field_schema_js_1 = require("../sequence-field-schema.js");
14
13
  const Sequence_js_1 = require("../Sequence.js");
15
14
  const SequenceContext_js_1 = require("../SequenceContext.js");
15
+ const truncate_src_for_label_js_1 = require("../truncate-src-for-label.js");
16
16
  const use_buffer_state_js_1 = require("../use-buffer-state.js");
17
17
  const use_delay_render_js_1 = require("../use-delay-render.js");
18
18
  const wrap_in_schema_js_1 = require("../wrap-in-schema.js");
19
- const canvasImageSchema = {
19
+ exports.canvasImageSchema = {
20
20
  fit: {
21
21
  type: 'enum',
22
22
  default: 'fill',
@@ -65,14 +65,14 @@ const loadImage = ({ src, signal, }) => {
65
65
  const imageWidth = image.naturalWidth || image.width;
66
66
  const imageHeight = image.naturalHeight || image.height;
67
67
  if (imageWidth <= 0 || imageHeight <= 0) {
68
- settle(() => reject(new Error(`Could not determine dimensions for <CanvasImage> with src="${(0, Img_js_1.truncateSrcForLabel)(src)}"`)));
68
+ settle(() => reject(new Error(`Could not determine dimensions for <CanvasImage> with src="${(0, truncate_src_for_label_js_1.truncateSrcForLabel)(src)}"`)));
69
69
  return;
70
70
  }
71
71
  settle(() => resolve({ element: image, width: imageWidth, height: imageHeight }));
72
72
  });
73
73
  };
74
74
  image.onerror = () => {
75
- settle(() => reject(new Error(`Could not load <CanvasImage> with src="${(0, Img_js_1.truncateSrcForLabel)(src)}"`)));
75
+ settle(() => reject(new Error(`Could not load <CanvasImage> with src="${(0, truncate_src_for_label_js_1.truncateSrcForLabel)(src)}"`)));
76
76
  };
77
77
  signal.addEventListener('abort', onAbort, { once: true });
78
78
  if (signal.aborted) {
@@ -86,7 +86,7 @@ const loadImage = ({ src, signal, }) => {
86
86
  function exponentialBackoff(errorCount) {
87
87
  return 1000 * 2 ** (errorCount - 1);
88
88
  }
89
- const CanvasImageContent = (0, react_1.forwardRef)(({ src, width, height, fit = 'fill', effects, controls, onError, className, style, id, pauseWhenLoading, maxRetries = 2, delayRenderRetries, delayRenderTimeoutInMilliseconds, }, ref) => {
89
+ const CanvasImageContent = (0, react_1.forwardRef)(({ src, width, height, fit = 'fill', effects, controls, onError, className, style, id, pauseWhenLoading, maxRetries = 2, delayRenderRetries, delayRenderTimeoutInMilliseconds, ...canvasProps }, ref) => {
90
90
  var _a;
91
91
  const { delayRender, continueRender, cancelRender } = (0, use_delay_render_js_1.useDelayRender)();
92
92
  const { delayPlayback } = (0, use_buffer_state_js_1.useBufferState)();
@@ -119,7 +119,7 @@ const CanvasImageContent = (0, react_1.forwardRef)(({ src, width, height, fit =
119
119
  }
120
120
  const isPremounting = Boolean(sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.premounting);
121
121
  const isPostmounting = Boolean(sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.postmounting);
122
- const handle = delayRender(`Rendering <CanvasImage> with src="${(0, Img_js_1.truncateSrcForLabel)(actualSrc)}"`, {
122
+ const handle = delayRender(`Rendering <CanvasImage> with src="${(0, truncate_src_for_label_js_1.truncateSrcForLabel)(actualSrc)}"`, {
123
123
  retries: delayRenderRetries !== null && delayRenderRetries !== void 0 ? delayRenderRetries : undefined,
124
124
  timeoutInMilliseconds: delayRenderTimeoutInMilliseconds !== null && delayRenderTimeoutInMilliseconds !== void 0 ? delayRenderTimeoutInMilliseconds : undefined,
125
125
  });
@@ -182,7 +182,7 @@ const CanvasImageContent = (0, react_1.forwardRef)(({ src, width, height, fit =
182
182
  if (errorCount <= maxRetries) {
183
183
  const backoff = exponentialBackoff(errorCount);
184
184
  // eslint-disable-next-line no-console
185
- console.warn(`Could not load <CanvasImage> with src="${(0, Img_js_1.truncateSrcForLabel)(actualSrc)}", retrying in ${backoff}ms`);
185
+ console.warn(`Could not load <CanvasImage> with src="${(0, truncate_src_for_label_js_1.truncateSrcForLabel)(actualSrc)}", retrying in ${backoff}ms`);
186
186
  timeoutId = setTimeout(() => {
187
187
  if (!cancelled) {
188
188
  attemptLoad();
@@ -228,20 +228,20 @@ const CanvasImageContent = (0, react_1.forwardRef)(({ src, width, height, fit =
228
228
  sourceCanvas,
229
229
  width,
230
230
  ]);
231
- return ((0, jsx_runtime_1.jsx)("canvas", { ref: canvasRef, width: width, height: height, className: className, style: style, id: id }));
231
+ return ((0, jsx_runtime_1.jsx)("canvas", { ...canvasProps, ref: canvasRef, width: width, height: height, className: className, style: style, id: id }));
232
232
  });
233
233
  CanvasImageContent.displayName = 'CanvasImageContent';
234
- const CanvasImageInner = (0, react_1.forwardRef)(({ src, width, height, fit, effects = [], className, style, id, onError, pauseWhenLoading, maxRetries, delayRenderRetries, delayRenderTimeoutInMilliseconds, durationInFrames, from, hidden, name, showInTimeline, stack, _experimentalControls: controls, }, ref) => {
234
+ const CanvasImageInner = (0, react_1.forwardRef)(({ src, width, height, fit, effects = [], className, style, id, onError, pauseWhenLoading, maxRetries, delayRenderRetries, delayRenderTimeoutInMilliseconds, durationInFrames, from, hidden, name, showInTimeline, stack, _experimentalControls: controls, _remotionInternalDocumentationLink, ...canvasProps }, ref) => {
235
235
  if (!src) {
236
236
  throw new Error('No "src" prop was passed to <CanvasImage>.');
237
237
  }
238
238
  const memoizedEffectDefinitions = (0, use_memoized_effects_js_1.useMemoizedEffectDefinitions)(effects);
239
- return ((0, jsx_runtime_1.jsx)(Sequence_js_1.Sequence, { layout: "none", from: from !== null && from !== void 0 ? from : 0, durationInFrames: durationInFrames !== null && durationInFrames !== void 0 ? durationInFrames : Infinity, hidden: hidden, showInTimeline: showInTimeline !== null && showInTimeline !== void 0 ? showInTimeline : true, name: name !== null && name !== void 0 ? name : '<CanvasImage>', _experimentalControls: controls, _remotionInternalEffects: memoizedEffectDefinitions, _remotionInternalIsMedia: { type: 'image', src }, _remotionInternalStack: stack, children: (0, jsx_runtime_1.jsx)(CanvasImageContent, { ref: ref, src: src, width: width, height: height, fit: fit, effects: effects, controls: controls, className: className, style: style, id: id, onError: onError, pauseWhenLoading: pauseWhenLoading, maxRetries: maxRetries, delayRenderRetries: delayRenderRetries, delayRenderTimeoutInMilliseconds: delayRenderTimeoutInMilliseconds }) }));
239
+ return ((0, jsx_runtime_1.jsx)(Sequence_js_1.Sequence, { layout: "none", from: from !== null && from !== void 0 ? from : 0, durationInFrames: durationInFrames !== null && durationInFrames !== void 0 ? durationInFrames : Infinity, 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', _experimentalControls: controls, _remotionInternalEffects: memoizedEffectDefinitions, _remotionInternalIsMedia: { type: 'image', src }, _remotionInternalStack: stack, children: (0, jsx_runtime_1.jsx)(CanvasImageContent, { ref: ref, src: src, width: width, height: height, fit: fit, effects: effects, controls: controls, className: className, style: style, id: id, onError: onError, pauseWhenLoading: pauseWhenLoading, maxRetries: maxRetries, delayRenderRetries: delayRenderRetries, delayRenderTimeoutInMilliseconds: delayRenderTimeoutInMilliseconds, ...canvasProps }) }));
240
240
  });
241
241
  /*
242
242
  * @description Renders a static image to a `<canvas>` and applies Remotion effects.
243
243
  * @see [Documentation](https://www.remotion.dev/docs/canvasimage)
244
244
  */
245
- exports.CanvasImage = (0, wrap_in_schema_js_1.wrapInSchema)(CanvasImageInner, canvasImageSchema);
245
+ exports.CanvasImage = (0, wrap_in_schema_js_1.wrapInSchema)(CanvasImageInner, exports.canvasImageSchema);
246
246
  exports.CanvasImage.displayName = 'CanvasImage';
247
247
  (0, enable_sequence_stack_traces_js_1.addSequenceStackTraces)(exports.CanvasImage);
@@ -8,7 +8,8 @@ type CanvasImageSequenceProps = Pick<SequenceProps, 'durationInFrames' | 'from'
8
8
  */
9
9
  readonly stack?: string;
10
10
  };
11
- export type CanvasImageProps = CanvasImageSequenceProps & {
11
+ export type CanvasImageCanvasProps = Omit<React.CanvasHTMLAttributes<HTMLCanvasElement>, 'children' | 'height' | 'onError' | 'width'>;
12
+ export type CanvasImageProps = CanvasImageSequenceProps & CanvasImageCanvasProps & {
12
13
  readonly src: string;
13
14
  readonly width?: number;
14
15
  readonly height?: number;
@@ -22,5 +23,9 @@ export type CanvasImageProps = CanvasImageSequenceProps & {
22
23
  readonly maxRetries?: number;
23
24
  readonly delayRenderRetries?: number;
24
25
  readonly delayRenderTimeoutInMilliseconds?: number;
26
+ /**
27
+ * @deprecated For internal use only.
28
+ */
29
+ readonly _remotionInternalDocumentationLink?: string;
25
30
  };
26
31
  export {};
@@ -32,8 +32,9 @@ const solidSchema = {
32
32
  description: 'Height',
33
33
  },
34
34
  ...sequence_field_schema_js_1.sequenceVisualStyleSchema,
35
+ hidden: sequence_field_schema_js_1.hiddenField,
35
36
  };
36
- const SolidInner = ({ color, width, height, effects = [], className, style, overrideId, ref, }) => {
37
+ const SolidInner = ({ color, width, height, effects = [], className, style, overrideId, reference, }) => {
37
38
  const { delayRender, continueRender, cancelRender } = (0, use_delay_render_js_1.useDelayRender)();
38
39
  const [outputCanvas, setOutputCanvas] = (0, react_1.useState)(null);
39
40
  const memoizedEffects = (0, use_memoized_effects_js_1.useMemoizedEffects)({
@@ -52,13 +53,13 @@ const SolidInner = ({ color, width, height, effects = [], className, style, over
52
53
  const chainState = (0, use_effect_chain_state_js_1.useEffectChainState)();
53
54
  const canvasRef = (0, react_1.useCallback)((canvas) => {
54
55
  setOutputCanvas(canvas);
55
- if (typeof ref === 'function') {
56
- ref(canvas);
56
+ if (typeof reference === 'function') {
57
+ reference(canvas);
57
58
  }
58
- else if (ref) {
59
- ref.current = canvas;
59
+ else if (reference) {
60
+ reference.current = canvas;
60
61
  }
61
- }, [ref]);
62
+ }, [reference]);
62
63
  // Fill source and run effect chain on every frame / color change.
63
64
  (0, react_1.useEffect)(() => {
64
65
  if (!outputCanvas || !sourceCanvas) {
@@ -118,7 +119,11 @@ const SolidOuter = (0, react_1.forwardRef)(({ effects = [], _experimentalControl
118
119
  var _a;
119
120
  props;
120
121
  const memoizedEffectDefinitions = (0, use_memoized_effects_js_1.useMemoizedEffectDefinitions)(effects);
121
- return ((0, jsx_runtime_1.jsx)(Sequence_js_1.Sequence, { layout: "none", from: from, hidden: hidden, showInTimeline: showInTimeline, _experimentalControls: controls, _remotionInternalEffects: memoizedEffectDefinitions, durationInFrames: durationInFrames, name: name !== null && name !== void 0 ? name : '<Solid>', _remotionInternalDocumentationLink: name === undefined ? 'https://www.remotion.dev/docs/solid' : undefined, ...props, children: (0, jsx_runtime_1.jsx)(SolidInner, { ref: ref, overrideId: (_a = controls === null || controls === void 0 ? void 0 : controls.overrideId) !== null && _a !== void 0 ? _a : null, color: color, height: height, width: width, className: className, style: style, effects: effects }) }));
122
+ const actualRef = (0, react_1.useRef)(null);
123
+ (0, react_1.useImperativeHandle)(ref, () => {
124
+ return actualRef.current;
125
+ }, []);
126
+ return ((0, jsx_runtime_1.jsx)(Sequence_js_1.Sequence, { layout: "none", from: from, hidden: hidden, showInTimeline: showInTimeline, _experimentalControls: controls, _remotionInternalEffects: memoizedEffectDefinitions, durationInFrames: durationInFrames, name: name !== null && name !== void 0 ? name : '<Solid>', _remotionInternalRefForOutline: actualRef, _remotionInternalDocumentationLink: name === undefined ? 'https://www.remotion.dev/docs/solid' : undefined, ...props, children: (0, jsx_runtime_1.jsx)(SolidInner, { reference: actualRef, overrideId: (_a = controls === null || controls === void 0 ? void 0 : controls.overrideId) !== null && _a !== void 0 ? _a : null, color: color, height: height, width: width, className: className, style: style, effects: effects }) }));
122
127
  });
123
128
  exports.Solid = (0, wrap_in_schema_js_1.wrapInSchema)(SolidOuter, solidSchema);
124
129
  exports.Solid.displayName = 'Solid';
@@ -270,7 +270,7 @@ export declare const Internals: {
270
270
  readonly getRoot: () => import("react").FC<{}> | null;
271
271
  readonly useMediaVolumeState: () => readonly [number, (u: number) => void];
272
272
  readonly useMediaMutedState: () => readonly [boolean, (u: React.SetStateAction<boolean>) => void];
273
- readonly useMediaInTimeline: ({ volume, mediaVolume, src, mediaType, playbackRate, displayName, id, getStack, showInTimeline, premountDisplay, postmountDisplay, loopDisplay, documentationLink, }: {
273
+ readonly useMediaInTimeline: ({ volume, mediaVolume, src, mediaType, playbackRate, displayName, id, getStack, showInTimeline, premountDisplay, postmountDisplay, loopDisplay, documentationLink, refForOutline, }: {
274
274
  volume: import("./volume-prop.js").VolumeProp | undefined;
275
275
  mediaVolume: number;
276
276
  src: string | undefined;
@@ -284,6 +284,7 @@ export declare const Internals: {
284
284
  postmountDisplay: number | null;
285
285
  loopDisplay: import("./CompositionManager.js").LoopDisplay | undefined;
286
286
  documentationLink: string | null;
287
+ refForOutline: React.RefObject<HTMLElement | null> | null;
287
288
  }) => void;
288
289
  readonly useLazyComponent: <Props>({ compProps, componentName, noSuspense, }: {
289
290
  compProps: CompProps<Props>;
@@ -66,8 +66,8 @@ function checkValidInputRange(arr) {
66
66
  }
67
67
  }
68
68
  function checkInfiniteRange(name, arr) {
69
- if (arr.length < 2) {
70
- throw new Error(name + ' must have at least 2 elements');
69
+ if (arr.length < 1) {
70
+ throw new Error(name + ' must have at least 1 element');
71
71
  }
72
72
  for (const element of arr) {
73
73
  if (typeof element !== 'number') {
@@ -143,6 +143,9 @@ function interpolate(input, inputRange, outputRange, options) {
143
143
  if (typeof input !== 'number') {
144
144
  throw new TypeError('Cannot interpolate an input which is not a number');
145
145
  }
146
+ if (inputRange.length === 1) {
147
+ return outputRange[0];
148
+ }
146
149
  const range = findRange(input, inputRange);
147
150
  return interpolateFunction(input, [inputRange[range], inputRange[range + 1]], [outputRange[range], outputRange[range + 1]], {
148
151
  easing: resolveEasingForSegment(range),