remotion 4.0.487 → 4.0.488

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cjs/Img.js CHANGED
@@ -23,6 +23,7 @@ const ImgContent = ({ onError, maxRetries = 2, src, pauseWhenLoading, delayRende
23
23
  const errors = (0, react_1.useRef)({});
24
24
  const { delayPlayback } = (0, use_buffer_state_js_1.useBufferState)();
25
25
  const sequenceContext = (0, react_1.useContext)(SequenceContext_js_1.SequenceContext);
26
+ const [isLoading, setIsLoading] = (0, react_1.useState)(false);
26
27
  const _propsValid = true;
27
28
  if (!_propsValid) {
28
29
  throw new Error('typecheck error');
@@ -59,6 +60,8 @@ const ImgContent = ({ onError, maxRetries = 2, src, pauseWhenLoading, delayRende
59
60
  }, timeout);
60
61
  }, []);
61
62
  const { delayRender, continueRender, cancelRender } = (0, use_delay_render_js_1.useDelayRender)();
63
+ const isPremounting = Boolean(sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.premounting);
64
+ const isPostmounting = Boolean(sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.postmounting);
62
65
  const didGetError = (0, react_1.useCallback)((e) => {
63
66
  var _a, _b, _c, _d, _e, _f, _g;
64
67
  var _h, _j, _k, _l;
@@ -89,8 +92,19 @@ const ImgContent = ({ onError, maxRetries = 2, src, pauseWhenLoading, delayRende
89
92
  }
90
93
  }, [cancelRender, maxRetries, onError, retryIn]);
91
94
  if (typeof window !== 'undefined') {
92
- const isPremounting = Boolean(sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.premounting);
93
- const isPostmounting = Boolean(sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.postmounting);
95
+ // eslint-disable-next-line react-hooks/rules-of-hooks
96
+ (0, react_1.useLayoutEffect)(() => {
97
+ if (!pauseWhenLoading || !isLoading || isPremounting || isPostmounting) {
98
+ return;
99
+ }
100
+ return delayPlayback().unblock;
101
+ }, [
102
+ delayPlayback,
103
+ isLoading,
104
+ isPostmounting,
105
+ isPremounting,
106
+ pauseWhenLoading,
107
+ ]);
94
108
  // eslint-disable-next-line react-hooks/rules-of-hooks
95
109
  (0, react_1.useLayoutEffect)(() => {
96
110
  var _a, _b;
@@ -104,13 +118,11 @@ const ImgContent = ({ onError, maxRetries = 2, src, pauseWhenLoading, delayRende
104
118
  if (!current) {
105
119
  return;
106
120
  }
121
+ setIsLoading(true);
107
122
  const newHandle = delayRender('Loading <Img> with src=' + (0, truncate_src_for_label_js_1.truncateSrcForLabel)(actualSrc), {
108
123
  retries: delayRenderRetries !== null && delayRenderRetries !== void 0 ? delayRenderRetries : undefined,
109
124
  timeoutInMilliseconds: delayRenderTimeoutInMilliseconds !== null && delayRenderTimeoutInMilliseconds !== void 0 ? delayRenderTimeoutInMilliseconds : undefined,
110
125
  });
111
- const unblock = pauseWhenLoading && !isPremounting && !isPostmounting
112
- ? delayPlayback().unblock
113
- : () => undefined;
114
126
  let unmounted = false;
115
127
  const onComplete = () => {
116
128
  var _a, _b, _c;
@@ -128,7 +140,7 @@ const ImgContent = ({ onError, maxRetries = 2, src, pauseWhenLoading, delayRende
128
140
  if (current) {
129
141
  onImageFrame === null || onImageFrame === void 0 ? void 0 : onImageFrame(current);
130
142
  }
131
- unblock();
143
+ setIsLoading(false);
132
144
  continueRender(newHandle);
133
145
  };
134
146
  if (!imageRef.current) {
@@ -158,17 +170,12 @@ const ImgContent = ({ onError, maxRetries = 2, src, pauseWhenLoading, delayRende
158
170
  return () => {
159
171
  unmounted = true;
160
172
  current.removeEventListener('load', onComplete);
161
- unblock();
162
173
  continueRender(newHandle);
163
174
  };
164
175
  }, [
165
176
  actualSrc,
166
- delayPlayback,
167
177
  delayRenderRetries,
168
178
  delayRenderTimeoutInMilliseconds,
169
- pauseWhenLoading,
170
- isPremounting,
171
- isPostmounting,
172
179
  onImageFrame,
173
180
  continueRender,
174
181
  delayRender,
@@ -1,8 +1,19 @@
1
1
  import type React from 'react';
2
2
  import type { SequenceControls } from '../CompositionManager.js';
3
3
  import type { EffectsProp } from '../effects/effect-types.js';
4
- import type { RemotionAnimatedImageProps } from './props';
5
- export declare const AnimatedImage: React.ComponentType<import("../Interactive.js").InteractiveBaseProps & RemotionAnimatedImageProps & {
4
+ export declare const AnimatedImage: React.ComponentType<import("../Interactive.js").InteractiveBaseProps & {
5
+ src: string;
6
+ width?: number | undefined;
7
+ height?: number | undefined;
8
+ onError?: ((error: Error) => void) | undefined;
9
+ fit?: import("../calculate-image-fit.js").ImageFit | undefined;
10
+ playbackRate?: number | undefined;
11
+ style?: React.CSSProperties | undefined;
12
+ loopBehavior?: import("./props").RemotionAnimatedImageLoopBehavior | undefined;
13
+ id?: string | undefined;
14
+ className?: string | undefined;
15
+ requestInit?: RequestInit | undefined;
16
+ } & React.AriaAttributes & Record<`data-${string}`, string | undefined> & {
6
17
  readonly effects?: EffectsProp | undefined;
7
18
  } & {
8
19
  readonly controls?: SequenceControls | undefined;
@@ -30,6 +30,17 @@ const animatedImageSchema = {
30
30
  },
31
31
  ...interactivity_schema_js_1.transformSchema,
32
32
  };
33
+ const getCanvasPropsFromSequenceProps = (props) => {
34
+ const canvasProps = {};
35
+ const mutableCanvasProps = canvasProps;
36
+ for (const key in props) {
37
+ if (Object.prototype.hasOwnProperty.call(props, key) &&
38
+ (key.startsWith('data-') || key.startsWith('aria-'))) {
39
+ mutableCanvasProps[key] = props[key];
40
+ }
41
+ }
42
+ return canvasProps;
43
+ };
33
44
  const AnimatedImageContent = (0, react_1.forwardRef)(({ src, width, height, onError, loopBehavior = 'loop', playbackRate = 1, fit = 'fill', requestInit, effects, controls, ...props }, canvasRef) => {
34
45
  var _a;
35
46
  const resolvedSrc = (0, resolve_image_source_1.resolveAnimatedImageSource)(src);
@@ -158,6 +169,7 @@ const AnimatedImageInner = ({ src, width, height, onError, fit, playbackRate, lo
158
169
  (0, react_1.useImperativeHandle)(ref, () => {
159
170
  return actualRef.current;
160
171
  }, []);
172
+ const canvasProps = getCanvasPropsFromSequenceProps(sequenceProps);
161
173
  const animatedImageProps = {
162
174
  src,
163
175
  width,
@@ -170,6 +182,7 @@ const AnimatedImageInner = ({ src, width, height, onError, fit, playbackRate, lo
170
182
  className,
171
183
  style,
172
184
  requestInit,
185
+ ...canvasProps,
173
186
  };
174
187
  return (jsx_runtime_1.jsx(Sequence_js_1.Sequence, { layout: "none", durationInFrames: resolvedDuration, name: "<AnimatedImage>", _remotionInternalDocumentationLink: "https://www.remotion.dev/docs/animatedimage", controls: controls, _remotionInternalEffects: memoizedEffectDefinitions, ...sequenceProps, outlineRef: actualRef, children: jsx_runtime_1.jsx(AnimatedImageContent, { ...animatedImageProps, ref: actualRef, effects: effects, controls: controls }) }));
175
188
  };
@@ -1,18 +1,15 @@
1
1
  import React from 'react';
2
2
  import type { EffectDefinitionAndStack } from '../effects/effect-types.js';
3
- import type { AnimatedImageFillMode } from './props';
4
- type Props = {
5
- readonly width?: number;
6
- readonly height?: number;
7
- readonly fit: AnimatedImageFillMode;
8
- readonly className?: string;
9
- readonly style?: React.CSSProperties;
10
- readonly effects: EffectDefinitionAndStack<unknown>[];
11
- };
12
3
  export type AnimatedImageCanvasRef = {
13
4
  readonly draw: (imageData: VideoFrame) => Promise<boolean>;
14
5
  readonly getCanvas: () => HTMLCanvasElement | null;
15
6
  clear: () => void;
16
7
  };
17
- export declare const Canvas: React.ForwardRefExoticComponent<Props & React.RefAttributes<AnimatedImageCanvasRef>>;
18
- export {};
8
+ export declare const Canvas: React.ForwardRefExoticComponent<{
9
+ readonly width?: number | undefined;
10
+ readonly height?: number | undefined;
11
+ readonly fit: import("../calculate-image-fit.js").ImageFit;
12
+ readonly className?: string | undefined;
13
+ readonly style?: React.CSSProperties | undefined;
14
+ readonly effects: EffectDefinitionAndStack<unknown>[];
15
+ } & React.AriaAttributes & Record<`data-${string}`, string | undefined> & React.RefAttributes<AnimatedImageCanvasRef>>;
@@ -39,7 +39,7 @@ const react_1 = __importStar(require("react"));
39
39
  const calculate_image_fit_js_1 = require("../calculate-image-fit.js");
40
40
  const run_effect_chain_js_1 = require("../effects/run-effect-chain.js");
41
41
  const use_effect_chain_state_js_1 = require("../effects/use-effect-chain-state.js");
42
- const CanvasRefForwardingFunction = ({ width, height, fit, className, style, effects }, ref) => {
42
+ const CanvasRefForwardingFunction = ({ width, height, fit, className, style, effects, ...props }, ref) => {
43
43
  const canvasRef = (0, react_1.useRef)(null);
44
44
  const chainState = (0, use_effect_chain_state_js_1.useEffectChainState)();
45
45
  const sourceCanvas = (0, react_1.useMemo)(() => {
@@ -101,6 +101,6 @@ const CanvasRefForwardingFunction = ({ width, height, fit, className, style, eff
101
101
  },
102
102
  };
103
103
  }, [draw]);
104
- return jsx_runtime_1.jsx("canvas", { ref: canvasRef, className: className, style: style });
104
+ return (jsx_runtime_1.jsx("canvas", { ref: canvasRef, className: className, style: style, ...props }));
105
105
  };
106
106
  exports.Canvas = react_1.default.forwardRef(CanvasRefForwardingFunction);
@@ -2,6 +2,7 @@ import type { ImageFit } from '../calculate-image-fit.js';
2
2
  import type { EffectsProp } from '../effects/effect-types.js';
3
3
  import type { InteractiveBaseProps } from '../Interactive.js';
4
4
  export type RemotionAnimatedImageLoopBehavior = 'loop' | 'pause-after-finish' | 'clear-after-finish';
5
+ export type AnimatedImageCanvasProps = React.AriaAttributes & Record<`data-${string}`, string | undefined>;
5
6
  export type RemotionAnimatedImageProps = {
6
7
  src: string;
7
8
  width?: number;
@@ -14,7 +15,7 @@ export type RemotionAnimatedImageProps = {
14
15
  id?: string;
15
16
  className?: string;
16
17
  requestInit?: RequestInit;
17
- };
18
+ } & AnimatedImageCanvasProps;
18
19
  export type AnimatedImageProps = InteractiveBaseProps & RemotionAnimatedImageProps & {
19
20
  readonly effects?: EffectsProp;
20
21
  };
@@ -33,6 +33,7 @@ export type ScheduleAudioNodeResult = {
33
33
  export type ScheduleAudioNodeOptions = {
34
34
  readonly node: AudioBufferSourceNode;
35
35
  readonly mediaTimestamp: number;
36
+ readonly sourceOffset: number;
36
37
  readonly scheduledTime: number;
37
38
  readonly originalUnloopedMediaTimestamp: number;
38
39
  readonly duration: number;
@@ -129,7 +129,7 @@ const SharedAudioContextProvider = ({ children, audioLatencyHint, audioEnabled,
129
129
  nodesToResume.current.delete(node);
130
130
  }, []);
131
131
  const scheduleAudioNode = (0, react_1.useMemo)(() => {
132
- return ({ node, mediaTimestamp, scheduledTime, duration, offset, originalUnloopedMediaTimestamp, }) => {
132
+ return ({ node, mediaTimestamp, sourceOffset, scheduledTime, duration, offset, originalUnloopedMediaTimestamp, }) => {
133
133
  if (!ctxAndGain) {
134
134
  throw new Error('Audio context not found');
135
135
  }
@@ -154,7 +154,7 @@ const SharedAudioContextProvider = ({ children, audioLatencyHint, audioEnabled,
154
154
  }
155
155
  }
156
156
  const scheduledEndTime = scheduledTime + duration / node.playbackRate.value;
157
- const mediaTime = mediaTimestamp + offset;
157
+ const mediaTime = mediaTimestamp + offset - sourceOffset;
158
158
  const mediaEndTime = mediaTime + duration;
159
159
  const latency = ctxAndGain.audioContext.baseLatency +
160
160
  ctxAndGain.audioContext.outputLatency;
@@ -108,13 +108,18 @@ const CanvasImageContent = (0, react_1.forwardRef)(({ src, width, height, fit =
108
108
  });
109
109
  const sequenceContext = (0, react_1.useContext)(SequenceContext_js_1.SequenceContext);
110
110
  const pendingLoadDelayRef = (0, react_1.useRef)(null);
111
- const continuePendingLoadDelay = (0, react_1.useCallback)(() => {
111
+ const [isLoadPending, setIsLoadPending] = (0, react_1.useState)(false);
112
+ const isPremounting = Boolean(sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.premounting);
113
+ const isPostmounting = Boolean(sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.postmounting);
114
+ const continuePendingLoadDelay = (0, react_1.useCallback)(({ markAsReady }) => {
112
115
  const pending = pendingLoadDelayRef.current;
113
116
  if (!pending || pending.continued) {
114
117
  return;
115
118
  }
116
119
  pending.continued = true;
117
- pending.unblock();
120
+ if (markAsReady) {
121
+ setIsLoadPending(false);
122
+ }
118
123
  continueRender(pending.handle);
119
124
  pendingLoadDelayRef.current = null;
120
125
  }, [continueRender]);
@@ -137,23 +142,33 @@ const CanvasImageContent = (0, react_1.forwardRef)(({ src, width, height, fit =
137
142
  }
138
143
  }, [ref, refForOutline]);
139
144
  (0, react_1.useLayoutEffect)(() => {
140
- const isPremounting = Boolean(sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.premounting);
141
- const isPostmounting = Boolean(sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.postmounting);
145
+ if (!pauseWhenLoading ||
146
+ !isLoadPending ||
147
+ isPremounting ||
148
+ isPostmounting) {
149
+ return;
150
+ }
151
+ return delayPlayback().unblock;
152
+ }, [
153
+ delayPlayback,
154
+ isLoadPending,
155
+ isPostmounting,
156
+ isPremounting,
157
+ pauseWhenLoading,
158
+ ]);
159
+ (0, react_1.useLayoutEffect)(() => {
142
160
  const handle = delayRender(`Rendering <CanvasImage> with src="${(0, truncate_src_for_label_js_1.truncateSrcForLabel)(actualSrc)}"`, {
143
161
  retries: delayRenderRetries !== null && delayRenderRetries !== void 0 ? delayRenderRetries : undefined,
144
162
  timeoutInMilliseconds: delayRenderTimeoutInMilliseconds !== null && delayRenderTimeoutInMilliseconds !== void 0 ? delayRenderTimeoutInMilliseconds : undefined,
145
163
  });
146
- const unblock = pauseWhenLoading && !isPremounting && !isPostmounting
147
- ? delayPlayback().unblock
148
- : () => undefined;
149
164
  const controller = new AbortController();
150
165
  let cancelled = false;
151
166
  let errorCount = 0;
152
167
  let timeoutId = null;
153
168
  setLoadedImage(null);
169
+ setIsLoadPending(true);
154
170
  pendingLoadDelayRef.current = {
155
171
  handle,
156
- unblock,
157
172
  continued: false,
158
173
  };
159
174
  const attemptLoad = () => {
@@ -166,7 +181,7 @@ const CanvasImageContent = (0, react_1.forwardRef)(({ src, width, height, fit =
166
181
  })
167
182
  .catch((err) => {
168
183
  if (err.name === 'AbortError') {
169
- continuePendingLoadDelay();
184
+ continuePendingLoadDelay({ markAsReady: false });
170
185
  return;
171
186
  }
172
187
  errorCount++;
@@ -182,7 +197,7 @@ const CanvasImageContent = (0, react_1.forwardRef)(({ src, width, height, fit =
182
197
  }
183
198
  else if (onError) {
184
199
  onError(err);
185
- continuePendingLoadDelay();
200
+ continuePendingLoadDelay({ markAsReady: true });
186
201
  }
187
202
  else {
188
203
  cancelRender(err);
@@ -196,21 +211,17 @@ const CanvasImageContent = (0, react_1.forwardRef)(({ src, width, height, fit =
196
211
  clearTimeout(timeoutId);
197
212
  }
198
213
  controller.abort();
199
- continuePendingLoadDelay();
214
+ continuePendingLoadDelay({ markAsReady: false });
200
215
  };
201
216
  }, [
202
217
  actualSrc,
203
218
  cancelRender,
204
219
  continuePendingLoadDelay,
205
- delayPlayback,
206
220
  delayRender,
207
221
  delayRenderRetries,
208
222
  delayRenderTimeoutInMilliseconds,
209
223
  maxRetries,
210
224
  onError,
211
- pauseWhenLoading,
212
- sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.postmounting,
213
- sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.premounting,
214
225
  ]);
215
226
  (0, react_1.useLayoutEffect)(() => {
216
227
  if (!loadedImage || !outputCanvas || !sourceCanvas) {
@@ -261,7 +272,7 @@ const CanvasImageContent = (0, react_1.forwardRef)(({ src, width, height, fit =
261
272
  return;
262
273
  }
263
274
  continueRenderOnce();
264
- continuePendingLoadDelay();
275
+ continuePendingLoadDelay({ markAsReady: true });
265
276
  },
266
277
  });
267
278
  }
@@ -273,7 +284,7 @@ const CanvasImageContent = (0, react_1.forwardRef)(({ src, width, height, fit =
273
284
  if (onError) {
274
285
  onError(err);
275
286
  continueRenderOnce();
276
- continuePendingLoadDelay();
287
+ continuePendingLoadDelay({ markAsReady: true });
277
288
  }
278
289
  else {
279
290
  cancelRender(err);
@@ -0,0 +1,8 @@
1
+ import { type InterpolateOptions } from './interpolate.js';
2
+ export type InterpolateTranslateOptions = InterpolateOptions;
3
+ export declare const interpolateTranslate: (input: number, inputRange: readonly number[], outputRange: readonly string[], options?: Partial<{
4
+ easing: import("./interpolate.js").EasingFunction | readonly import("./interpolate.js").EasingFunction[];
5
+ extrapolateLeft: import("./interpolate.js").ExtrapolateType;
6
+ extrapolateRight: import("./interpolate.js").ExtrapolateType;
7
+ posterize: number;
8
+ }> | undefined) => string;
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.interpolateTranslate = void 0;
4
+ const interpolate_js_1 = require("./interpolate.js");
5
+ const pixelValueRegex = /^([+-]?(?:\d+\.?\d*|\.\d+))px$/;
6
+ const parseTranslate = (value) => {
7
+ if (typeof value !== 'string') {
8
+ throw new TypeError(`outputRange must contain only strings, but got ${typeof value}`);
9
+ }
10
+ const parts = value.trim().split(/\s+/);
11
+ if (parts.length < 1 || parts.length > 3 || parts[0] === '') {
12
+ throw new TypeError(`translate values must contain 1 to 3 pixel values, but got "${value}"`);
13
+ }
14
+ return parts.map((part) => {
15
+ const match = pixelValueRegex.exec(part);
16
+ if (match === null) {
17
+ throw new TypeError(`interpolateTranslate() only supports px values, but got "${part}" in "${value}"`);
18
+ }
19
+ return Number(match[1]);
20
+ });
21
+ };
22
+ /*
23
+ * @description Allows you to map a range of values to CSS translate values using pixel units.
24
+ * @see [Documentation](https://remotion.dev/docs/interpolate-translate)
25
+ */
26
+ const interpolateTranslate = (input, inputRange, outputRange, options) => {
27
+ var _a;
28
+ if (typeof input === 'undefined') {
29
+ throw new TypeError('input can not be undefined');
30
+ }
31
+ if (typeof inputRange === 'undefined') {
32
+ throw new TypeError('inputRange can not be undefined');
33
+ }
34
+ if (typeof outputRange === 'undefined') {
35
+ throw new TypeError('outputRange can not be undefined');
36
+ }
37
+ if (inputRange.length !== outputRange.length) {
38
+ throw new TypeError('inputRange (' +
39
+ inputRange.length +
40
+ ' values provided) and outputRange (' +
41
+ outputRange.length +
42
+ ' values provided) must have the same length');
43
+ }
44
+ const parsedOutputRange = outputRange.map((translateValue) => parseTranslate(translateValue));
45
+ const firstValueLength = (_a = parsedOutputRange[0]) === null || _a === void 0 ? void 0 : _a.length;
46
+ if (firstValueLength === undefined) {
47
+ throw new TypeError('outputRange must have at least 1 element');
48
+ }
49
+ for (const parsedTranslate of parsedOutputRange) {
50
+ if (parsedTranslate.length !== firstValueLength) {
51
+ throw new TypeError(`All translate values must have the same number of pixel values, but got ${firstValueLength} and ${parsedTranslate.length}`);
52
+ }
53
+ }
54
+ return new Array(firstValueLength)
55
+ .fill(true)
56
+ .map((_, index) => {
57
+ const outputValues = [];
58
+ for (const translateValue of parsedOutputRange) {
59
+ const value = translateValue[index];
60
+ if (value === undefined) {
61
+ throw new TypeError(`All translate values must have the same number of pixel values, but got ${firstValueLength} and ${translateValue.length}`);
62
+ }
63
+ outputValues.push(value);
64
+ }
65
+ const interpolatedValue = (0, interpolate_js_1.interpolate)(input, inputRange, outputValues, options);
66
+ return `${interpolatedValue}px`;
67
+ })
68
+ .join(' ');
69
+ };
70
+ exports.interpolateTranslate = interpolateTranslate;
@@ -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.487";
6
+ export declare const VERSION = "4.0.488";
@@ -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.487';
10
+ exports.VERSION = '4.0.488';
@@ -1,16 +1,16 @@
1
1
  import React from 'react';
2
2
  import type { SequenceControls } from './CompositionManager.js';
3
- import { type InteractivitySchema } from './interactivity-schema.js';
3
+ import { type SequenceSchema } from './sequence-field-schema.js';
4
4
  export declare const getNestedValue: (obj: Record<string, unknown>, key: string) => unknown;
5
5
  export declare const readValuesFromProps: (props: Record<string, unknown>, keys: string[]) => Record<string, unknown>;
6
- export declare const selectActiveKeys: (schema: InteractivitySchema, values: Record<string, unknown>) => string[];
6
+ export declare const selectActiveKeys: (schema: SequenceSchema, values: Record<string, unknown>) => string[];
7
7
  export declare const mergeValues: ({ props, valuesDotNotation, schemaKeys, propsToDelete, }: {
8
8
  props: Record<string, unknown>;
9
9
  valuesDotNotation: Record<string, unknown>;
10
10
  schemaKeys: string[];
11
11
  propsToDelete: Set<string>;
12
12
  }) => Record<string, unknown>;
13
- export declare const wrapInSchema: <S extends InteractivitySchema, Props extends object>({ Component, componentIdentity, schema, supportsEffects, }: {
13
+ export declare const wrapInSchema: <S extends SequenceSchema, Props extends object>({ Component, componentIdentity, schema, supportsEffects, }: {
14
14
  Component: React.ComponentType<Props & {
15
15
  readonly _experimentalControls: SequenceControls | undefined;
16
16
  }>;
@@ -38,7 +38,7 @@ const react_1 = __importStar(require("react"));
38
38
  const delete_nested_key_js_1 = require("./delete-nested-key.js");
39
39
  const use_memoized_effects_js_1 = require("./effects/use-memoized-effects.js");
40
40
  const flatten_schema_js_1 = require("./flatten-schema.js");
41
- const interactivity_schema_js_1 = require("./interactivity-schema.js");
41
+ const sequence_field_schema_js_1 = require("./sequence-field-schema.js");
42
42
  const sequence_node_path_js_1 = require("./sequence-node-path.js");
43
43
  const SequenceManager_js_1 = require("./SequenceManager.js");
44
44
  const use_current_frame_js_1 = require("./use-current-frame.js");
@@ -100,7 +100,7 @@ exports.mergeValues = mergeValues;
100
100
  const stackToOverrideMap = {};
101
101
  const wrapInSchema = ({ Component, componentIdentity, schema, supportsEffects, }) => {
102
102
  // Schema is static for a component, so we move this outside
103
- const schemaWithSequenceName = (0, interactivity_schema_js_1.extendSchemaWithSequenceName)(schema);
103
+ const schemaWithSequenceName = (0, sequence_field_schema_js_1.extendSchemaWithSequenceName)(schema);
104
104
  const flatSchema = (0, flatten_schema_js_1.getFlatSchemaWithAllKeys)(schemaWithSequenceName);
105
105
  const flatKeys = Object.keys(flatSchema);
106
106
  const Wrapped = (0, react_1.forwardRef)((props, ref) => {
@@ -1291,7 +1291,7 @@ var addSequenceStackTraces = (component) => {
1291
1291
  };
1292
1292
 
1293
1293
  // src/version.ts
1294
- var VERSION = "4.0.487";
1294
+ var VERSION = "4.0.488";
1295
1295
 
1296
1296
  // src/multiple-versions-warning.ts
1297
1297
  var checkMultipleRemotionVersions = () => {
@@ -5124,7 +5124,7 @@ var useEffectChainState = () => {
5124
5124
 
5125
5125
  // src/animated-image/canvas.tsx
5126
5126
  import { jsx as jsx13 } from "react/jsx-runtime";
5127
- var CanvasRefForwardingFunction = ({ width, height, fit, className, style, effects }, ref) => {
5127
+ var CanvasRefForwardingFunction = ({ width, height, fit, className, style, effects, ...props }, ref) => {
5128
5128
  const canvasRef = useRef8(null);
5129
5129
  const chainState = useEffectChainState();
5130
5130
  const sourceCanvas = useMemo16(() => {
@@ -5188,7 +5188,8 @@ var CanvasRefForwardingFunction = ({ width, height, fit, className, style, effec
5188
5188
  return /* @__PURE__ */ jsx13("canvas", {
5189
5189
  ref: canvasRef,
5190
5190
  className,
5191
- style
5191
+ style,
5192
+ ...props
5192
5193
  });
5193
5194
  };
5194
5195
  var Canvas = React15.forwardRef(CanvasRefForwardingFunction);
@@ -5374,6 +5375,16 @@ var animatedImageSchema = {
5374
5375
  },
5375
5376
  ...transformSchema
5376
5377
  };
5378
+ var getCanvasPropsFromSequenceProps = (props) => {
5379
+ const canvasProps = {};
5380
+ const mutableCanvasProps = canvasProps;
5381
+ for (const key in props) {
5382
+ if (Object.prototype.hasOwnProperty.call(props, key) && (key.startsWith("data-") || key.startsWith("aria-"))) {
5383
+ mutableCanvasProps[key] = props[key];
5384
+ }
5385
+ }
5386
+ return canvasProps;
5387
+ };
5377
5388
  var AnimatedImageContent = forwardRef4(({
5378
5389
  src,
5379
5390
  width,
@@ -5528,6 +5539,7 @@ var AnimatedImageInner = ({
5528
5539
  useImperativeHandle2(ref, () => {
5529
5540
  return actualRef.current;
5530
5541
  }, []);
5542
+ const canvasProps = getCanvasPropsFromSequenceProps(sequenceProps);
5531
5543
  const animatedImageProps = {
5532
5544
  src,
5533
5545
  width,
@@ -5539,7 +5551,8 @@ var AnimatedImageInner = ({
5539
5551
  id,
5540
5552
  className,
5541
5553
  style,
5542
- requestInit
5554
+ requestInit,
5555
+ ...canvasProps
5543
5556
  };
5544
5557
  return /* @__PURE__ */ jsx14(Sequence, {
5545
5558
  layout: "none",
@@ -6567,6 +6580,7 @@ var SharedAudioContextProvider = ({ children, audioLatencyHint, audioEnabled, pr
6567
6580
  return ({
6568
6581
  node,
6569
6582
  mediaTimestamp,
6583
+ sourceOffset,
6570
6584
  scheduledTime,
6571
6585
  duration,
6572
6586
  offset,
@@ -6595,7 +6609,7 @@ var SharedAudioContextProvider = ({ children, audioLatencyHint, audioEnabled, pr
6595
6609
  }
6596
6610
  }
6597
6611
  const scheduledEndTime = scheduledTime + duration / node.playbackRate.value;
6598
- const mediaTime = mediaTimestamp + offset;
6612
+ const mediaTime = mediaTimestamp + offset - sourceOffset;
6599
6613
  const mediaEndTime = mediaTime + duration;
6600
6614
  const latency = ctxAndGain.audioContext.baseLatency + ctxAndGain.audioContext.outputLatency;
6601
6615
  const timeDiff = scheduledTime - ctxAndGain.audioContext.currentTime;
@@ -9527,13 +9541,18 @@ var CanvasImageContent = forwardRef10(({
9527
9541
  });
9528
9542
  const sequenceContext = useContext32(SequenceContext);
9529
9543
  const pendingLoadDelayRef = useRef23(null);
9530
- const continuePendingLoadDelay = useCallback17(() => {
9544
+ const [isLoadPending, setIsLoadPending] = useState16(false);
9545
+ const isPremounting = Boolean(sequenceContext?.premounting);
9546
+ const isPostmounting = Boolean(sequenceContext?.postmounting);
9547
+ const continuePendingLoadDelay = useCallback17(({ markAsReady }) => {
9531
9548
  const pending = pendingLoadDelayRef.current;
9532
9549
  if (!pending || pending.continued) {
9533
9550
  return;
9534
9551
  }
9535
9552
  pending.continued = true;
9536
- pending.unblock();
9553
+ if (markAsReady) {
9554
+ setIsLoadPending(false);
9555
+ }
9537
9556
  continueRender2(pending.handle);
9538
9557
  pendingLoadDelayRef.current = null;
9539
9558
  }, [continueRender2]);
@@ -9555,23 +9574,30 @@ var CanvasImageContent = forwardRef10(({
9555
9574
  }
9556
9575
  }, [ref, refForOutline]);
9557
9576
  useLayoutEffect10(() => {
9558
- const isPremounting = Boolean(sequenceContext?.premounting);
9559
- const isPostmounting = Boolean(sequenceContext?.postmounting);
9577
+ if (!pauseWhenLoading || !isLoadPending || isPremounting || isPostmounting) {
9578
+ return;
9579
+ }
9580
+ return delayPlayback().unblock;
9581
+ }, [
9582
+ delayPlayback,
9583
+ isLoadPending,
9584
+ isPostmounting,
9585
+ isPremounting,
9586
+ pauseWhenLoading
9587
+ ]);
9588
+ useLayoutEffect10(() => {
9560
9589
  const handle = delayRender2(`Rendering <CanvasImage> with src="${truncateSrcForLabel(actualSrc)}"`, {
9561
9590
  retries: delayRenderRetries ?? undefined,
9562
9591
  timeoutInMilliseconds: delayRenderTimeoutInMilliseconds ?? undefined
9563
9592
  });
9564
- const unblock = pauseWhenLoading && !isPremounting && !isPostmounting ? delayPlayback().unblock : () => {
9565
- return;
9566
- };
9567
9593
  const controller = new AbortController;
9568
9594
  let cancelled = false;
9569
9595
  let errorCount = 0;
9570
9596
  let timeoutId = null;
9571
9597
  setLoadedImage(null);
9598
+ setIsLoadPending(true);
9572
9599
  pendingLoadDelayRef.current = {
9573
9600
  handle,
9574
- unblock,
9575
9601
  continued: false
9576
9602
  };
9577
9603
  const attemptLoad = () => {
@@ -9582,7 +9608,7 @@ var CanvasImageContent = forwardRef10(({
9582
9608
  setLoadedImage(image);
9583
9609
  }).catch((err) => {
9584
9610
  if (err.name === "AbortError") {
9585
- continuePendingLoadDelay();
9611
+ continuePendingLoadDelay({ markAsReady: false });
9586
9612
  return;
9587
9613
  }
9588
9614
  errorCount++;
@@ -9596,7 +9622,7 @@ var CanvasImageContent = forwardRef10(({
9596
9622
  }, backoff);
9597
9623
  } else if (onError) {
9598
9624
  onError(err);
9599
- continuePendingLoadDelay();
9625
+ continuePendingLoadDelay({ markAsReady: true });
9600
9626
  } else {
9601
9627
  cancelRender2(err);
9602
9628
  }
@@ -9609,21 +9635,17 @@ var CanvasImageContent = forwardRef10(({
9609
9635
  clearTimeout(timeoutId);
9610
9636
  }
9611
9637
  controller.abort();
9612
- continuePendingLoadDelay();
9638
+ continuePendingLoadDelay({ markAsReady: false });
9613
9639
  };
9614
9640
  }, [
9615
9641
  actualSrc,
9616
9642
  cancelRender2,
9617
9643
  continuePendingLoadDelay,
9618
- delayPlayback,
9619
9644
  delayRender2,
9620
9645
  delayRenderRetries,
9621
9646
  delayRenderTimeoutInMilliseconds,
9622
9647
  maxRetries,
9623
- onError,
9624
- pauseWhenLoading,
9625
- sequenceContext?.postmounting,
9626
- sequenceContext?.premounting
9648
+ onError
9627
9649
  ]);
9628
9650
  useLayoutEffect10(() => {
9629
9651
  if (!loadedImage || !outputCanvas || !sourceCanvas) {
@@ -9675,7 +9697,7 @@ var CanvasImageContent = forwardRef10(({
9675
9697
  return;
9676
9698
  }
9677
9699
  continueRenderOnce();
9678
- continuePendingLoadDelay();
9700
+ continuePendingLoadDelay({ markAsReady: true });
9679
9701
  }
9680
9702
  });
9681
9703
  }
@@ -9686,7 +9708,7 @@ var CanvasImageContent = forwardRef10(({
9686
9708
  if (onError) {
9687
9709
  onError(err);
9688
9710
  continueRenderOnce();
9689
- continuePendingLoadDelay();
9711
+ continuePendingLoadDelay({ markAsReady: true });
9690
9712
  } else {
9691
9713
  cancelRender2(err);
9692
9714
  }
@@ -9871,7 +9893,13 @@ var IFrameRefForwarding = ({
9871
9893
  };
9872
9894
  var IFrame = forwardRef11(IFrameRefForwarding);
9873
9895
  // src/Img.tsx
9874
- import { useCallback as useCallback19, useContext as useContext33, useLayoutEffect as useLayoutEffect11, useRef as useRef24 } from "react";
9896
+ import {
9897
+ useCallback as useCallback19,
9898
+ useContext as useContext33,
9899
+ useLayoutEffect as useLayoutEffect11,
9900
+ useRef as useRef24,
9901
+ useState as useState18
9902
+ } from "react";
9875
9903
  import { jsx as jsx28 } from "react/jsx-runtime";
9876
9904
  function exponentialBackoff2(errorCount) {
9877
9905
  return 1000 * 2 ** (errorCount - 1);
@@ -9894,6 +9922,7 @@ var ImgContent = ({
9894
9922
  const errors = useRef24({});
9895
9923
  const { delayPlayback } = useBufferState();
9896
9924
  const sequenceContext = useContext33(SequenceContext);
9925
+ const [isLoading, setIsLoading] = useState18(false);
9897
9926
  const _propsValid = true;
9898
9927
  if (!_propsValid) {
9899
9928
  throw new Error("typecheck error");
@@ -9926,6 +9955,8 @@ var ImgContent = ({
9926
9955
  }, timeout);
9927
9956
  }, []);
9928
9957
  const { delayRender: delayRender2, continueRender: continueRender2, cancelRender: cancelRender2 } = useDelayRender();
9958
+ const isPremounting = Boolean(sequenceContext?.premounting);
9959
+ const isPostmounting = Boolean(sequenceContext?.postmounting);
9929
9960
  const didGetError = useCallback19((e) => {
9930
9961
  if (!errors.current) {
9931
9962
  return;
@@ -9946,8 +9977,18 @@ var ImgContent = ({
9946
9977
  } catch {}
9947
9978
  }, [cancelRender2, maxRetries, onError, retryIn]);
9948
9979
  if (typeof window !== "undefined") {
9949
- const isPremounting = Boolean(sequenceContext?.premounting);
9950
- const isPostmounting = Boolean(sequenceContext?.postmounting);
9980
+ useLayoutEffect11(() => {
9981
+ if (!pauseWhenLoading || !isLoading || isPremounting || isPostmounting) {
9982
+ return;
9983
+ }
9984
+ return delayPlayback().unblock;
9985
+ }, [
9986
+ delayPlayback,
9987
+ isLoading,
9988
+ isPostmounting,
9989
+ isPremounting,
9990
+ pauseWhenLoading
9991
+ ]);
9951
9992
  useLayoutEffect11(() => {
9952
9993
  if (window.process?.env?.NODE_ENV === "test") {
9953
9994
  if (imageRef.current) {
@@ -9959,13 +10000,11 @@ var ImgContent = ({
9959
10000
  if (!current) {
9960
10001
  return;
9961
10002
  }
10003
+ setIsLoading(true);
9962
10004
  const newHandle = delayRender2("Loading <Img> with src=" + truncateSrcForLabel(actualSrc), {
9963
10005
  retries: delayRenderRetries ?? undefined,
9964
10006
  timeoutInMilliseconds: delayRenderTimeoutInMilliseconds ?? undefined
9965
10007
  });
9966
- const unblock = pauseWhenLoading && !isPremounting && !isPostmounting ? delayPlayback().unblock : () => {
9967
- return;
9968
- };
9969
10008
  let unmounted = false;
9970
10009
  const onComplete = () => {
9971
10010
  if (unmounted) {
@@ -9979,7 +10018,7 @@ var ImgContent = ({
9979
10018
  if (current) {
9980
10019
  onImageFrame?.(current);
9981
10020
  }
9982
- unblock();
10021
+ setIsLoading(false);
9983
10022
  continueRender2(newHandle);
9984
10023
  };
9985
10024
  if (!imageRef.current) {
@@ -9998,17 +10037,12 @@ var ImgContent = ({
9998
10037
  return () => {
9999
10038
  unmounted = true;
10000
10039
  current.removeEventListener("load", onComplete);
10001
- unblock();
10002
10040
  continueRender2(newHandle);
10003
10041
  };
10004
10042
  }, [
10005
10043
  actualSrc,
10006
- delayPlayback,
10007
10044
  delayRenderRetries,
10008
10045
  delayRenderTimeoutInMilliseconds,
10009
- pauseWhenLoading,
10010
- isPremounting,
10011
- isPostmounting,
10012
10046
  onImageFrame,
10013
10047
  continueRender2,
10014
10048
  delayRender2
@@ -10334,7 +10368,7 @@ import {
10334
10368
  useImperativeHandle as useImperativeHandle8,
10335
10369
  useMemo as useMemo32,
10336
10370
  useRef as useRef26,
10337
- useState as useState18
10371
+ useState as useState19
10338
10372
  } from "react";
10339
10373
  import { jsx as jsx30 } from "react/jsx-runtime";
10340
10374
  var CompositionManagerProvider = ({
@@ -10344,9 +10378,9 @@ var CompositionManagerProvider = ({
10344
10378
  initialCompositions,
10345
10379
  initialCanvasContent
10346
10380
  }) => {
10347
- const [folders, setFolders] = useState18([]);
10348
- const [canvasContent, setCanvasContent] = useState18(initialCanvasContent);
10349
- const [compositions, setCompositions] = useState18(initialCompositions);
10381
+ const [folders, setFolders] = useState19([]);
10382
+ const [canvasContent, setCanvasContent] = useState19(initialCanvasContent);
10383
+ const [compositions, setCompositions] = useState19(initialCompositions);
10350
10384
  const currentcompositionsRef = useRef26(compositions);
10351
10385
  const updateCompositions = useCallback21((updateComps) => {
10352
10386
  setCompositions((comps) => {
@@ -10921,7 +10955,7 @@ import {
10921
10955
  useEffect as useEffect17,
10922
10956
  useLayoutEffect as useLayoutEffect12,
10923
10957
  useMemo as useMemo35,
10924
- useState as useState19
10958
+ useState as useState20
10925
10959
  } from "react";
10926
10960
 
10927
10961
  // src/video/offthread-video-source.ts
@@ -11036,7 +11070,7 @@ var OffthreadVideoForRendering = ({
11036
11070
  toneMapped
11037
11071
  });
11038
11072
  }, [toneMapped, currentTime, src, transparent]);
11039
- const [imageSrc, setImageSrc] = useState19(null);
11073
+ const [imageSrc, setImageSrc] = useState20(null);
11040
11074
  const { delayRender: delayRender2, continueRender: continueRender2 } = useDelayRender();
11041
11075
  useLayoutEffect12(() => {
11042
11076
  if (!window.remotion_videoEnabled) {
@@ -11148,7 +11182,7 @@ import React37, {
11148
11182
  useImperativeHandle as useImperativeHandle9,
11149
11183
  useMemo as useMemo36,
11150
11184
  useRef as useRef27,
11151
- useState as useState20
11185
+ useState as useState21
11152
11186
  } from "react";
11153
11187
 
11154
11188
  // src/video/emit-video-frame.ts
@@ -11259,7 +11293,7 @@ var VideoForDevelopmentRefForwardingFunction = (props2, ref) => {
11259
11293
  const parentSequence = useContext37(SequenceContext);
11260
11294
  const logLevel = useLogLevel();
11261
11295
  const mountTime = useMountTime();
11262
- const [timelineId] = useState20(() => String(Math.random()));
11296
+ const [timelineId] = useState21(() => String(Math.random()));
11263
11297
  if (typeof acceptableTimeShift !== "undefined") {
11264
11298
  throw new Error("acceptableTimeShift has been removed. Use acceptableTimeShiftInSeconds instead.");
11265
11299
  }
@@ -11330,7 +11364,7 @@ var VideoForDevelopmentRefForwardingFunction = (props2, ref) => {
11330
11364
  useImperativeHandle9(ref, () => {
11331
11365
  return videoRef.current;
11332
11366
  }, []);
11333
- useState20(() => playbackLogging({
11367
+ useState21(() => playbackLogging({
11334
11368
  logLevel,
11335
11369
  message: `Mounting video with source = ${actualSrc}, v=${VERSION}, user agent=${typeof navigator === "undefined" ? "server" : navigator.userAgent}`,
11336
11370
  tag: "video",
@@ -1,5 +1,5 @@
1
1
  // src/version.ts
2
- var VERSION = "4.0.487";
2
+ var VERSION = "4.0.488";
3
3
  export {
4
4
  VERSION
5
5
  };
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "url": "https://github.com/remotion-dev/remotion/tree/main/packages/core"
4
4
  },
5
5
  "name": "remotion",
6
- "version": "4.0.487",
6
+ "version": "4.0.488",
7
7
  "description": "Make videos programmatically",
8
8
  "main": "dist/cjs/index.js",
9
9
  "types": "dist/cjs/index.d.ts",
@@ -35,7 +35,7 @@
35
35
  "react-dom": "19.2.3",
36
36
  "webpack": "5.105.0",
37
37
  "zod": "4.3.6",
38
- "@remotion/eslint-config-internal": "4.0.487",
38
+ "@remotion/eslint-config-internal": "4.0.488",
39
39
  "eslint": "9.19.0",
40
40
  "@typescript/native-preview": "7.0.0-dev.20260217.1"
41
41
  },