remotion 4.0.506 → 4.0.508

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.
Files changed (35) hide show
  1. package/README.md +1 -0
  2. package/dist/cjs/Interactive.d.ts +10 -0
  3. package/dist/cjs/SequenceManager.d.ts +6 -0
  4. package/dist/cjs/SequenceManager.js +20 -0
  5. package/dist/cjs/audio/shared-audio-tags.d.ts +2 -1
  6. package/dist/cjs/audio/shared-audio-tags.js +22 -6
  7. package/dist/cjs/audio/wait-until-actually-resumed.d.ts +2 -1
  8. package/dist/cjs/audio/wait-until-actually-resumed.js +34 -4
  9. package/dist/cjs/buffering.js +17 -8
  10. package/dist/cjs/interactivity-schema.d.ts +10 -0
  11. package/dist/cjs/interactivity-schema.js +8 -0
  12. package/dist/cjs/internals.d.ts +6 -3
  13. package/dist/cjs/internals.js +4 -0
  14. package/dist/cjs/interpolate-keyframed-status.js +2 -0
  15. package/dist/cjs/interpolate.js +92 -11
  16. package/dist/cjs/portal-node.d.ts +3 -0
  17. package/dist/cjs/portal-node.js +22 -1
  18. package/dist/cjs/render-resource-manager.d.ts +13 -0
  19. package/dist/cjs/render-resource-manager.js +47 -0
  20. package/dist/cjs/sequence-node-path.d.ts +1 -1
  21. package/dist/cjs/use-current-scale.js +10 -6
  22. package/dist/cjs/use-schema.d.ts +4 -1
  23. package/dist/cjs/version.d.ts +1 -1
  24. package/dist/cjs/version.js +1 -1
  25. package/dist/cjs/with-interactivity-schema.js +3 -1
  26. package/dist/esm/index.mjs +296 -77
  27. package/dist/esm/no-react.mjs +100 -16
  28. package/dist/esm/version.mjs +1 -1
  29. package/package.json +2 -2
  30. package/dist/cjs/interpolate-translate.d.ts +0 -8
  31. package/dist/cjs/interpolate-translate.js +0 -70
  32. package/dist/cjs/sequence-field-schema.d.ts +0 -425
  33. package/dist/cjs/sequence-field-schema.js +0 -133
  34. package/dist/cjs/wrap-in-schema.d.ts +0 -20
  35. package/dist/cjs/wrap-in-schema.js +0 -203
package/README.md CHANGED
@@ -48,6 +48,7 @@ Remotion is extensively documented over more than 1000 pages.
48
48
  - [Prompts](https://www.remotion.dev/prompts)
49
49
  - [Templates](https://remotion.dev/templates)
50
50
  - Components
51
+ - [Elements](https://remotion.dev/elements)
51
52
  - [Effects](https://remotion.dev/effects)
52
53
  - [Shapes](https://remotion.dev/docs/shapes)
53
54
  - [Transitions](https://remotion.dev/transitions)
@@ -296,6 +296,11 @@ export declare const Interactive: {
296
296
  };
297
297
  };
298
298
  svgPaintSchema: {
299
+ readonly color: {
300
+ readonly type: "color";
301
+ readonly default: undefined;
302
+ readonly description: "Current color";
303
+ };
299
304
  readonly stroke: {
300
305
  readonly type: "color";
301
306
  readonly default: "none";
@@ -316,6 +321,11 @@ export declare const Interactive: {
316
321
  };
317
322
  };
318
323
  svgStrokeSchema: {
324
+ readonly color: {
325
+ readonly type: "color";
326
+ readonly default: undefined;
327
+ readonly description: "Current color";
328
+ };
319
329
  readonly stroke: {
320
330
  readonly type: "color";
321
331
  readonly default: "none";
@@ -22,12 +22,18 @@ export type VisualModeDragOverrides = {
22
22
  getDragOverrides: GetDragOverrides;
23
23
  getEffectDragOverrides: GetEffectDragOverrides;
24
24
  };
25
+ export type SequencePropsStatusRemapping = {
26
+ previousNodePath: SequencePropsSubscriptionKey;
27
+ nodePath: SequencePropsSubscriptionKey | null;
28
+ result: CanUpdateSequencePropsResponse | null;
29
+ };
25
30
  export type VisualModeSetters = {
26
31
  setDragOverrides: (nodePath: SequencePropsSubscriptionKey, key: string, value: DragOverrideValue) => void;
27
32
  clearDragOverrides: (nodePath: SequencePropsSubscriptionKey) => void;
28
33
  setEffectDragOverrides: (nodePath: SequencePropsSubscriptionKey, effectIndex: number, key: string, value: DragOverrideValue) => void;
29
34
  clearEffectDragOverrides: (nodePath: SequencePropsSubscriptionKey, effectIndex: number) => void;
30
35
  setPropStatuses: (nodePath: SequencePropsSubscriptionKey, values: (prev: CanUpdateSequencePropsResponse) => CanUpdateSequencePropsResponse) => void;
36
+ remapPropStatuses: (remappings: readonly SequencePropsStatusRemapping[]) => void;
31
37
  };
32
38
  export type CanUpdateEffectPropsResponseTrue = {
33
39
  canUpdate: true;
@@ -82,6 +82,9 @@ exports.VisualModeSettersContext = react_1.default.createContext({
82
82
  setPropStatuses: () => {
83
83
  throw new Error('VisualModeSettersContext not initialized');
84
84
  },
85
+ remapPropStatuses: () => {
86
+ throw new Error('VisualModeSettersContext not initialized');
87
+ },
85
88
  });
86
89
  const effectDragOverridesKey = (nodePath, effectIndex) => `${(0, exports.makeSequencePropsSubscriptionKey)(nodePath)}.effects.${effectIndex}`;
87
90
  const SequenceManagerProvider = ({ children }) => {
@@ -149,6 +152,21 @@ const SequenceManagerProvider = ({ children }) => {
149
152
  return { ...prev, [key]: newKey };
150
153
  });
151
154
  }, []);
155
+ const remapPropStatuses = (0, react_1.useCallback)((remappings) => {
156
+ setPropStatusesMapState((prev) => {
157
+ const next = { ...prev };
158
+ for (const remapping of remappings) {
159
+ delete next[(0, exports.makeSequencePropsSubscriptionKey)(remapping.previousNodePath)];
160
+ }
161
+ for (const remapping of remappings) {
162
+ if (remapping.nodePath !== null && remapping.result !== null) {
163
+ next[(0, exports.makeSequencePropsSubscriptionKey)(remapping.nodePath)] =
164
+ remapping.result;
165
+ }
166
+ }
167
+ return next;
168
+ });
169
+ }, []);
152
170
  const registerSequence = (0, react_1.useCallback)((seq) => {
153
171
  setSequences((seqs) => {
154
172
  return [...seqs, seq];
@@ -190,6 +208,7 @@ const SequenceManagerProvider = ({ children }) => {
190
208
  setEffectDragOverrides,
191
209
  clearEffectDragOverrides,
192
210
  setPropStatuses,
211
+ remapPropStatuses,
193
212
  };
194
213
  }, [
195
214
  setDragOverrides,
@@ -197,6 +216,7 @@ const SequenceManagerProvider = ({ children }) => {
197
216
  setEffectDragOverrides,
198
217
  clearEffectDragOverrides,
199
218
  setPropStatuses,
219
+ remapPropStatuses,
200
220
  ]);
201
221
  return (jsx_runtime_1.jsx(exports.SequenceManagerRefContext.Provider, { value: sequencesRef, children: jsx_runtime_1.jsx(exports.SequenceManager.Provider, { value: sequenceContext, children: jsx_runtime_1.jsx(exports.VisualModePropStatusesRefContext.Provider, { value: propStatusesRef, children: jsx_runtime_1.jsx(exports.VisualModePropStatusesContext.Provider, { value: propStatusesContext, children: jsx_runtime_1.jsx(exports.VisualModeDragOverridesContext.Provider, { value: dragOverridesContext, children: jsx_runtime_1.jsx(exports.VisualModeSettersContext.Provider, { value: settersContext, children: children }) }) }) }) }) }));
202
222
  };
@@ -1,6 +1,7 @@
1
1
  import React, { type AudioHTMLAttributes } from 'react';
2
2
  import type { SharedElementSourceNode } from './shared-element-source-node.js';
3
3
  import type { RemotionAudioContextState } from './use-audio-context.js';
4
+ import { type AudioContextResumeResult } from './wait-until-actually-resumed.js';
4
5
  /**
5
6
  * This functionality of Remotion will keep a certain amount
6
7
  * of <audio> tags pre-mounted and by default filled with an empty audio track.
@@ -58,7 +59,7 @@ type SharedAudioContextValue = {
58
59
  scheduleAudioNode: (options: ScheduleAudioNodeOptions) => ScheduleAudioNodeResult;
59
60
  resume: () => Promise<void>;
60
61
  suspend: () => Promise<void>;
61
- getIsResumingAudioContext: () => Promise<void> | null;
62
+ getIsResumingAudioContext: () => Promise<AudioContextResumeResult> | null;
62
63
  unscheduleAudioNode: (node: AudioBufferSourceNode) => void;
63
64
  };
64
65
  type SharedAudioTagsContextValue = {
@@ -105,6 +105,7 @@ const SharedAudioContextProvider = ({ children, audioLatencyHint, audioEnabled,
105
105
  });
106
106
  const audioContextIsPlayingEventually = (0, react_1.useRef)(false);
107
107
  const isResuming = (0, react_1.useRef)(null);
108
+ const nextResumeAttemptId = (0, react_1.useRef)(0);
108
109
  const audioSyncAnchor = (0, react_1.useMemo)(() => ({ value: 0 }), []);
109
110
  const audioSyncAnchorListeners = (0, react_1.useRef)([]);
110
111
  const audioSyncAnchorEmitter = (0, react_1.useMemo)(() => {
@@ -203,24 +204,39 @@ const SharedAudioContextProvider = ({ children, audioLatencyHint, audioEnabled,
203
204
  });
204
205
  nodesToResume.current.clear();
205
206
  const resumePromise = ctxAndGain.resume();
206
- isResuming.current = new Promise((resolve) => {
207
- (0, wait_until_actually_resumed_js_1.waitUntilActuallyResumed)(ctxAndGain.audioContext, logLevel).then(resolve);
207
+ const abortController = new AbortController();
208
+ const resumeAttemptId = nextResumeAttemptId.current++;
209
+ const waitPromise = new Promise((resolve) => {
210
+ (0, wait_until_actually_resumed_js_1.waitUntilActuallyResumed)(ctxAndGain.audioContext, logLevel, abortController.signal).then(resolve);
208
211
  resumePromise.catch((err) => {
209
- log_js_1.Log.warn({ logLevel, tag: 'audio' }, 'AudioContext resume rejected, continuing without audio sync', err);
210
- resolve();
212
+ log_js_1.Log.warn({ logLevel, tag: 'audio' }, 'AudioContext resume rejected, muting playback and continuing without audio', err);
213
+ abortController.abort();
214
+ resolve('failed');
211
215
  });
212
216
  }).finally(() => {
213
- isResuming.current = null;
217
+ var _a;
218
+ if (((_a = isResuming.current) === null || _a === void 0 ? void 0 : _a.id) === resumeAttemptId) {
219
+ isResuming.current = null;
220
+ }
214
221
  });
222
+ isResuming.current = {
223
+ abortController,
224
+ id: resumeAttemptId,
225
+ promise: waitPromise,
226
+ };
215
227
  return resumePromise.catch(() => {
216
228
  // Already logged above; swallow to avoid unhandled rejection
217
229
  // since callers (e.g. use-playback.ts) do not await this.
218
230
  });
219
231
  }, [ctxAndGain, logLevel]);
220
232
  const getIsResumingAudioContext = (0, react_1.useCallback)(() => {
221
- return isResuming.current;
233
+ var _a;
234
+ var _b;
235
+ return (_b = (_a = isResuming.current) === null || _a === void 0 ? void 0 : _a.promise) !== null && _b !== void 0 ? _b : null;
222
236
  }, []);
223
237
  const suspend = (0, react_1.useCallback)(() => {
238
+ var _a;
239
+ (_a = isResuming.current) === null || _a === void 0 ? void 0 : _a.abortController.abort();
224
240
  if (!ctxAndGain) {
225
241
  return Promise.resolve();
226
242
  }
@@ -1 +1,2 @@
1
- export declare const waitUntilActuallyResumed: (audioContext: AudioContext, logLevel: "error" | "info" | "trace" | "verbose" | "warn") => Promise<void>;
1
+ export type AudioContextResumeResult = 'resumed' | 'cancelled' | 'failed';
2
+ export declare const waitUntilActuallyResumed: (audioContext: AudioContext, logLevel: "error" | "info" | "trace" | "verbose" | "warn", signal: AbortSignal) => Promise<AudioContextResumeResult>;
@@ -2,15 +2,36 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.waitUntilActuallyResumed = void 0;
4
4
  const log_js_1 = require("../log.js");
5
- const waitUntilActuallyResumed = (audioContext, logLevel) => {
5
+ const RESUME_WAIT_TIMEOUT = 1000;
6
+ const waitUntilActuallyResumed = (audioContext, logLevel, signal) => {
6
7
  return new Promise((resolve) => {
7
8
  const startCurrentTime = audioContext.currentTime;
8
9
  const start = audioContext.getOutputTimestamp();
9
10
  const startOutputPerformanceTime = start.performanceTime;
10
11
  const startWallClock = performance.now();
12
+ let animationFrame = null;
13
+ let timeout = null;
14
+ let settled = false;
15
+ let onAbort = () => undefined;
16
+ const finish = (result) => {
17
+ if (settled) {
18
+ return;
19
+ }
20
+ settled = true;
21
+ if (animationFrame !== null) {
22
+ cancelAnimationFrame(animationFrame);
23
+ }
24
+ if (timeout !== null) {
25
+ clearTimeout(timeout);
26
+ }
27
+ signal.removeEventListener('abort', onAbort);
28
+ resolve(result);
29
+ };
30
+ onAbort = () => finish('cancelled');
11
31
  const check = () => {
12
32
  var _a;
13
33
  var _b;
34
+ animationFrame = null;
14
35
  const { currentTime } = audioContext;
15
36
  const outputTimestamp = audioContext.getOutputTimestamp();
16
37
  const elapsedWallClock = performance.now() - startWallClock;
@@ -20,12 +41,21 @@ const waitUntilActuallyResumed = (audioContext, logLevel) => {
20
41
  outputTimestamp.contextTime !== undefined &&
21
42
  outputTimestamp.contextTime > startCurrentTime) {
22
43
  log_js_1.Log.verbose({ logLevel, tag: 'audio' }, `waitUntilActuallyResumed: getOutputTimestamp.performanceTime advanced from ${startOutputPerformanceTime.toFixed(6)} to ${outputTimestamp.performanceTime.toFixed(6)} after ${elapsedWallClock.toFixed(1)}ms. currentTime=${currentTime.toFixed(6)} (advanced by ${(currentTime - startCurrentTime).toFixed(6)}), getOutputTimestamp.performanceTime=${(_b = (_a = outputTimestamp.performanceTime) === null || _a === void 0 ? void 0 : _a.toFixed(1)) !== null && _b !== void 0 ? _b : 'undefined'}`);
23
- resolve();
44
+ finish('resumed');
24
45
  return;
25
46
  }
26
- requestAnimationFrame(check);
47
+ animationFrame = requestAnimationFrame(check);
27
48
  };
28
- requestAnimationFrame(check);
49
+ if (signal.aborted) {
50
+ finish('cancelled');
51
+ return;
52
+ }
53
+ signal.addEventListener('abort', onAbort, { once: true });
54
+ timeout = setTimeout(() => {
55
+ log_js_1.Log.warn({ logLevel, tag: 'audio' }, 'WARNING: You enabled autoPlay on an unmuted <Player /> and the browser did not allow the video to be started. Remotion muted the <Player /> so it can play. To properly handle this, either set the `muted` prop or remove the `autoPlay` prop');
56
+ finish('failed');
57
+ }, RESUME_WAIT_TIMEOUT);
58
+ animationFrame = requestAnimationFrame(check);
29
59
  });
30
60
  };
31
61
  exports.waitUntilActuallyResumed = waitUntilActuallyResumed;
@@ -41,8 +41,14 @@ const playback_logging_1 = require("./playback-logging");
41
41
  const use_remotion_environment_1 = require("./use-remotion-environment");
42
42
  const useBufferManager = (logLevel, mountTime) => {
43
43
  const [blocks, setBlocks] = (0, react_1.useState)([]);
44
- const [onBufferingCallbacks, setOnBufferingCallbacks] = (0, react_1.useState)([]);
45
- const [onResumeCallbacks, setOnResumeCallbacks] = (0, react_1.useState)([]);
44
+ // Listener registries are refs, not state: `usePlayback` parks its loop
45
+ // during buffering and registers its resume listener from a rAF callback.
46
+ // With state, that registration only lands after the next React commit -
47
+ // if the last block unblocks before then, the resume dispatch reads the
48
+ // previous array, the listener is never called, and the playback loop
49
+ // stays parked forever (frame clock frozen while isPlaying() is true).
50
+ const onBufferingCallbacks = (0, react_1.useRef)([]);
51
+ const onResumeCallbacks = (0, react_1.useRef)([]);
46
52
  const env = (0, use_remotion_environment_1.useRemotionEnvironment)();
47
53
  const rendering = env.isRendering;
48
54
  const buffering = (0, react_1.useRef)(false);
@@ -71,18 +77,21 @@ const useBufferManager = (logLevel, mountTime) => {
71
77
  };
72
78
  }, [rendering]);
73
79
  const listenForBuffering = (0, react_1.useCallback)((callback) => {
74
- setOnBufferingCallbacks((c) => [...c, callback]);
80
+ onBufferingCallbacks.current = [
81
+ ...onBufferingCallbacks.current,
82
+ callback,
83
+ ];
75
84
  return {
76
85
  remove: () => {
77
- setOnBufferingCallbacks((c) => c.filter((cb) => cb !== callback));
86
+ onBufferingCallbacks.current = onBufferingCallbacks.current.filter((cb) => cb !== callback);
78
87
  },
79
88
  };
80
89
  }, []);
81
90
  const listenForResume = (0, react_1.useCallback)((callback) => {
82
- setOnResumeCallbacks((c) => [...c, callback]);
91
+ onResumeCallbacks.current = [...onResumeCallbacks.current, callback];
83
92
  return {
84
93
  remove: () => {
85
- setOnResumeCallbacks((c) => c.filter((cb) => cb !== callback));
94
+ onResumeCallbacks.current = onResumeCallbacks.current.filter((cb) => cb !== callback);
86
95
  },
87
96
  };
88
97
  }, []);
@@ -95,7 +104,7 @@ const useBufferManager = (logLevel, mountTime) => {
95
104
  // not re-dispatch `waiting` to listeners.
96
105
  if (blocks.length > 0 && !buffering.current) {
97
106
  buffering.current = true;
98
- onBufferingCallbacks.forEach((c) => c());
107
+ [...onBufferingCallbacks.current].forEach((c) => c());
99
108
  (0, playback_logging_1.playbackLogging)({
100
109
  logLevel,
101
110
  message: 'Player is entering buffer state',
@@ -119,7 +128,7 @@ const useBufferManager = (logLevel, mountTime) => {
119
128
  // dispatch `resume` to listeners.
120
129
  if (blocks.length === 0 && buffering.current) {
121
130
  buffering.current = false;
122
- onResumeCallbacks.forEach((c) => c());
131
+ [...onResumeCallbacks.current].forEach((c) => c());
123
132
  (0, playback_logging_1.playbackLogging)({
124
133
  logLevel,
125
134
  message: 'Player is exiting buffer state',
@@ -386,6 +386,11 @@ export declare const backgroundSchema: {
386
386
  };
387
387
  };
388
388
  export declare const svgStrokeSchema: {
389
+ readonly color: {
390
+ readonly type: "color";
391
+ readonly default: undefined;
392
+ readonly description: "Current color";
393
+ };
389
394
  readonly stroke: {
390
395
  readonly type: "color";
391
396
  readonly default: "none";
@@ -401,6 +406,11 @@ export declare const svgStrokeSchema: {
401
406
  };
402
407
  };
403
408
  export declare const svgPaintSchema: {
409
+ readonly color: {
410
+ readonly type: "color";
411
+ readonly default: undefined;
412
+ readonly description: "Current color";
413
+ };
404
414
  readonly stroke: {
405
415
  readonly type: "color";
406
416
  readonly default: "none";
@@ -208,7 +208,15 @@ exports.backgroundSchema = {
208
208
  description: 'Color',
209
209
  },
210
210
  };
211
+ const svgColorSchema = {
212
+ color: {
213
+ type: 'color',
214
+ default: undefined,
215
+ description: 'Current color',
216
+ },
217
+ };
211
218
  exports.svgStrokeSchema = {
219
+ ...svgColorSchema,
212
220
  stroke: {
213
221
  type: 'color',
214
222
  // `none` is the SVG initial value of stroke.
@@ -14,7 +14,7 @@ import type { OverrideIdToNodePaths, OverrideToNodePathGetters, OverrideToNodeSe
14
14
  import { OverrideIdsToNodePathsGettersContext, OverrideIdsToNodePathsSettersContext } from './sequence-node-path.js';
15
15
  import type { ResolvedStackLocation } from './sequence-stack-traces.js';
16
16
  import type { CannotUpdateSequenceReason } from './SequenceManager.js';
17
- import { type CanUpdateEffectPropsResponse, type CanUpdateEffectPropsResponseFalse, type CanUpdateEffectPropsResponseTrue, type CanUpdateSequencePropsResponse, type CanUpdateSequencePropsResponseFalse, type CanUpdateSequencePropsResponseTrue, type SequenceNodePath, type SequencePropsSubscriptionKey, type VideoConfigValues } from './SequenceManager.js';
17
+ import { type CanUpdateEffectPropsResponse, type CanUpdateEffectPropsResponseFalse, type CanUpdateEffectPropsResponseTrue, type CanUpdateSequencePropsResponse, type CanUpdateSequencePropsResponseFalse, type CanUpdateSequencePropsResponseTrue, type SequenceNodePath, type SequencePropsSubscriptionKey, type SequencePropsStatusRemapping, type VideoConfigValues } from './SequenceManager.js';
18
18
  import * as TimelinePosition from './timeline-position-state.js';
19
19
  import { type PlaybackRateContextValue, type SetTimelineContextValue, type TimelineImperativeContextValue, type TimelineContextValue } from './TimelineContext.js';
20
20
  import { truthy } from './truthy.js';
@@ -26,6 +26,8 @@ import { useRemotionContexts } from './wrap-remotion-context.js';
26
26
  export type { EffectChainState } from './effects/run-effect-chain.js';
27
27
  export declare const Internals: {
28
28
  readonly MaxMediaCacheSizeContext: import("react").Context<number | null>;
29
+ readonly makeRenderResourceManager: () => import("./render-resource-manager.js").RenderResourceManager;
30
+ readonly RenderResourceManagerContext: import("react").Context<import("./render-resource-manager.js").RenderResourceManager | null>;
29
31
  readonly useUnsafeVideoConfig: () => import("./video-config.js").VideoConfig | null;
30
32
  readonly useFrameForVolumeProp: (behavior: import("./index.js").LoopVolumeCurveBehavior) => number;
31
33
  readonly useTimelinePosition: () => number;
@@ -812,7 +814,7 @@ export declare const Internals: {
812
814
  scheduleAudioNode: (options: ScheduleAudioNodeOptions) => ScheduleAudioNodeResult;
813
815
  resume: () => Promise<void>;
814
816
  suspend: () => Promise<void>;
815
- getIsResumingAudioContext: () => Promise<void> | null;
817
+ getIsResumingAudioContext: () => Promise<import("./audio/wait-until-actually-resumed.js").AudioContextResumeResult> | null;
816
818
  unscheduleAudioNode: (node: AudioBufferSourceNode) => void;
817
819
  } | null>;
818
820
  readonly SharedAudioContextProvider: import("react").FC<{
@@ -873,6 +875,7 @@ export declare const Internals: {
873
875
  getCompositions: () => import("./CompositionManager.js").AnyComposition[];
874
876
  } | null>;
875
877
  readonly portalNode: () => HTMLElement;
878
+ readonly setPortalNodeCurrentScale: (scale: number) => void;
876
879
  readonly waitForRoot: (fn: (comp: import("react").FC<{}>) => void) => () => void;
877
880
  readonly SetTimelineContext: import("react").Context<SetTimelineContextValue>;
878
881
  readonly CanUseRemotionHooksProvider: import("react").FC<{
@@ -1270,4 +1273,4 @@ export declare const Internals: {
1270
1273
  readonly componentName: string;
1271
1274
  }) => import("react").CSSProperties | null;
1272
1275
  };
1273
- export type { ArrayFieldSchema, AssetFieldSchema, ArrayItemFieldSchema, CannotUpdateSequenceReason, CanUpdateEffectPropsResponse, CanUpdateEffectPropsResponseFalse, CanUpdateEffectPropsResponseTrue, CanUpdateSequencePropsResponse, CanUpdateSequencePropsResponseFalse, CanUpdateSequencePropsResponseTrue, CanUpdateSequencePropStatus, CanUpdateSequencePropStatusEasing, CanUpdateSequencePropStatusFalse, CanUpdateSequencePropStatusKeyframed, CanUpdateSequencePropStatusStatic, VideoConfigNumericExpression, CompositionManagerContext, CompProps, DragOverrides, DragOverrideValue, EffectDragOverrides, GetDragOverrides, GetEffectDragOverrides, GetEffectPropStatuses, GetPropStatuses, JsxComponentIdentity, LoggingContextValue, MediaVolumeContextValue, NonceHistory, OverrideIdsToNodePathsGettersContext, OverrideIdsToNodePathsSettersContext, OverrideIdToNodePaths, OverrideToNodePathGetters, OverrideToNodeSetters, PlaybackRateContextValue, PropStatuses, RemotionAudioContextState, RemotionEnvironment, ResolvedStackLocation, ScheduleAudioNodeOptions, ScheduleAudioNodeResult, InteractivitySchemaField, SequenceNodePath, SequencePropsSubscriptionKey, VideoConfigValues, InteractivitySchema, SerializedJSONWithCustomFields, SetMediaVolumeContextValue, SetTimelineContextValue, TCompMetadata, TComposition, TimelineContextValue, TimelineImperativeContextValue, TRenderAsset, TSequence, VisibleFieldSchema, WatchRemotionStaticFilesPayload, };
1276
+ export type { ArrayFieldSchema, AssetFieldSchema, ArrayItemFieldSchema, CannotUpdateSequenceReason, CanUpdateEffectPropsResponse, CanUpdateEffectPropsResponseFalse, CanUpdateEffectPropsResponseTrue, CanUpdateSequencePropsResponse, CanUpdateSequencePropsResponseFalse, CanUpdateSequencePropsResponseTrue, CanUpdateSequencePropStatus, CanUpdateSequencePropStatusEasing, CanUpdateSequencePropStatusFalse, CanUpdateSequencePropStatusKeyframed, CanUpdateSequencePropStatusStatic, VideoConfigNumericExpression, CompositionManagerContext, CompProps, DragOverrides, DragOverrideValue, EffectDragOverrides, GetDragOverrides, GetEffectDragOverrides, GetEffectPropStatuses, GetPropStatuses, JsxComponentIdentity, LoggingContextValue, MediaVolumeContextValue, NonceHistory, OverrideIdsToNodePathsGettersContext, OverrideIdsToNodePathsSettersContext, OverrideIdToNodePaths, OverrideToNodePathGetters, OverrideToNodeSetters, PlaybackRateContextValue, PropStatuses, RemotionAudioContextState, RemotionEnvironment, ResolvedStackLocation, ScheduleAudioNodeOptions, ScheduleAudioNodeResult, InteractivitySchemaField, SequenceNodePath, SequencePropsSubscriptionKey, SequencePropsStatusRemapping, VideoConfigValues, InteractivitySchema, SerializedJSONWithCustomFields, SetMediaVolumeContextValue, SetTimelineContextValue, TCompMetadata, TComposition, TimelineContextValue, TimelineImperativeContextValue, TRenderAsset, TSequence, VisibleFieldSchema, WatchRemotionStaticFilesPayload, };
@@ -78,6 +78,7 @@ const PremountContext_js_1 = require("./PremountContext.js");
78
78
  const register_root_js_1 = require("./register-root.js");
79
79
  const remotion_environment_context_js_1 = require("./remotion-environment-context.js");
80
80
  const RemotionRoot_js_1 = require("./RemotionRoot.js");
81
+ const render_resource_manager_js_1 = require("./render-resource-manager.js");
81
82
  const RenderAssetManager_js_1 = require("./RenderAssetManager.js");
82
83
  const resolve_video_config_js_1 = require("./resolve-video-config.js");
83
84
  const ResolveCompositionConfig_js_1 = require("./ResolveCompositionConfig.js");
@@ -123,6 +124,8 @@ const compositionSelectorRef = (0, react_1.createRef)();
123
124
  // API and are less likely to use it
124
125
  exports.Internals = {
125
126
  MaxMediaCacheSizeContext: max_video_cache_size_js_1.MaxMediaCacheSizeContext,
127
+ makeRenderResourceManager: render_resource_manager_js_1.makeRenderResourceManager,
128
+ RenderResourceManagerContext: render_resource_manager_js_1.RenderResourceManagerContext,
126
129
  useUnsafeVideoConfig: use_unsafe_video_config_js_1.useUnsafeVideoConfig,
127
130
  useFrameForVolumeProp: use_audio_frame_js_1.useFrameForVolumeProp,
128
131
  useTimelinePosition: TimelinePosition.useTimelinePosition,
@@ -188,6 +191,7 @@ exports.Internals = {
188
191
  getPreviewDomElement: get_preview_dom_element_js_1.getPreviewDomElement,
189
192
  compositionsRef: CompositionManager_js_1.compositionsRef,
190
193
  portalNode: portal_node_js_1.portalNode,
194
+ setPortalNodeCurrentScale: portal_node_js_1.setPortalNodeCurrentScale,
191
195
  waitForRoot: register_root_js_1.waitForRoot,
192
196
  SetTimelineContext: TimelineContext_js_1.SetTimelineContext,
193
197
  CanUseRemotionHooksProvider: CanUseRemotionHooks_js_1.CanUseRemotionHooksProvider,
@@ -10,6 +10,8 @@ const easingToFn = ({ easing, forceSpringAllowTail, }) => {
10
10
  switch (easing.type) {
11
11
  case 'linear':
12
12
  return easing_js_1.Easing.linear;
13
+ case 'step1':
14
+ return easing_js_1.Easing.step1;
13
15
  case 'spring':
14
16
  return easing_js_1.Easing.spring({
15
17
  allowTail: (_a = forceSpringAllowTail !== null && forceSpringAllowTail !== void 0 ? forceSpringAllowTail : easing.allowTail) !== null && _a !== void 0 ? _a : undefined,
@@ -206,9 +206,49 @@ const parseTransformOriginValue = (output, parts) => {
206
206
  });
207
207
  return {
208
208
  kind: 'translate',
209
- values: [x.value, y.value, z.value],
210
- units: [x.unit, y.unit, z.unit],
209
+ values: [x.value, y.value, z.value, 0],
210
+ units: [x.unit, y.unit, z.unit, null],
211
211
  dimensions: parts[2] === undefined ? 2 : 3,
212
+ axisRotation: false,
213
+ };
214
+ };
215
+ const parseAxisRotationValue = (output) => {
216
+ const parts = output.trim().split(/\s+/);
217
+ const keywordAxis = parts.length === 2 ? parts[0].toLowerCase() : null;
218
+ if (keywordAxis === 'x' || keywordAxis === 'y' || keywordAxis === 'z') {
219
+ const keywordAngle = parseStringInterpolationComponent(parts[1], output);
220
+ if (keywordAngle.kind !== 'rotate') {
221
+ return null;
222
+ }
223
+ return {
224
+ kind: 'rotate',
225
+ values: keywordAxis === 'x'
226
+ ? [1, 0, 0, keywordAngle.value]
227
+ : keywordAxis === 'y'
228
+ ? [0, 1, 0, keywordAngle.value]
229
+ : [0, 0, 1, keywordAngle.value],
230
+ units: [null, null, null, keywordAngle.unit],
231
+ dimensions: 4,
232
+ axisRotation: true,
233
+ };
234
+ }
235
+ if (parts.length !== 4) {
236
+ return null;
237
+ }
238
+ const axis = parts.slice(0, 3).map(Number);
239
+ if (!axis.every(Number.isFinite)) {
240
+ return null;
241
+ }
242
+ const vectorAngle = parseStringInterpolationComponent(parts[3], output);
243
+ if (vectorAngle.kind !== 'rotate') {
244
+ return null;
245
+ }
246
+ return {
247
+ kind: 'rotate',
248
+ values: [axis[0], axis[1], axis[2], vectorAngle.value],
249
+ units: [null, null, null, vectorAngle.unit],
250
+ dimensions: 4,
251
+ axisRotation: true,
212
252
  };
213
253
  };
214
254
  const parseStringInterpolationValue = (output) => {
@@ -220,11 +260,16 @@ const parseStringInterpolationValue = (output) => {
220
260
  }
221
261
  return {
222
262
  kind: 'scale',
223
- values: [output, output, 1],
224
- units: [null, null, null],
263
+ values: [output, output, 1, 0],
264
+ units: [null, null, null, null],
225
265
  dimensions: 1,
266
+ axisRotation: false,
226
267
  };
227
268
  }
269
+ const axisRotation = parseAxisRotationValue(output);
270
+ if (axisRotation !== null) {
271
+ return axisRotation;
272
+ }
228
273
  const parts = output.trim().split(/\s+/);
229
274
  if (parts.length < 1 || parts.length > 3 || parts[0] === '') {
230
275
  throw new TypeError(`String outputRange values must contain 1 to 3 components, but got "${output}"`);
@@ -245,19 +290,29 @@ const parseStringInterpolationValue = (output) => {
245
290
  const z = (_h = (_b = parsed[2]) === null || _b === void 0 ? void 0 : _b.value) !== null && _h !== void 0 ? _h : 1;
246
291
  return {
247
292
  kind,
248
- values: [x, y, z],
249
- units: [null, null, null],
293
+ values: [x, y, z, 0],
294
+ units: [null, null, null, null],
250
295
  dimensions: parsed.length,
296
+ axisRotation: false,
251
297
  };
252
298
  }
253
299
  return {
254
300
  kind,
255
- values: [parsed[0].value, (_j = (_c = parsed[1]) === null || _c === void 0 ? void 0 : _c.value) !== null && _j !== void 0 ? _j : 0, (_k = (_d = parsed[2]) === null || _d === void 0 ? void 0 : _d.value) !== null && _k !== void 0 ? _k : 0],
256
- units: [parsed[0].unit, (_l = (_e = parsed[1]) === null || _e === void 0 ? void 0 : _e.unit) !== null && _l !== void 0 ? _l : null, (_m = (_f = parsed[2]) === null || _f === void 0 ? void 0 : _f.unit) !== null && _m !== void 0 ? _m : null],
301
+ values: [parsed[0].value, (_j = (_c = parsed[1]) === null || _c === void 0 ? void 0 : _c.value) !== null && _j !== void 0 ? _j : 0, (_k = (_d = parsed[2]) === null || _d === void 0 ? void 0 : _d.value) !== null && _k !== void 0 ? _k : 0, 0],
302
+ units: [
303
+ parsed[0].unit,
304
+ (_l = (_e = parsed[1]) === null || _e === void 0 ? void 0 : _e.unit) !== null && _l !== void 0 ? _l : null,
305
+ (_m = (_f = parsed[2]) === null || _f === void 0 ? void 0 : _f.unit) !== null && _m !== void 0 ? _m : null,
306
+ null,
307
+ ],
257
308
  dimensions: parsed.length,
309
+ axisRotation: false,
258
310
  };
259
311
  };
260
- const serializeStringInterpolationValue = ({ kind, values, units, dimensions, }) => {
312
+ const serializeStringInterpolationValue = ({ kind, values, units, dimensions, axisRotation, }) => {
313
+ if (axisRotation) {
314
+ return `${stringifyNumber(values[0])} ${stringifyNumber(values[1])} ${stringifyNumber(values[2])} ${stringifyNumber(values[3])}${units[3]}`;
315
+ }
261
316
  if (kind === 'scale') {
262
317
  return values
263
318
  .slice(0, dimensions)
@@ -430,7 +485,28 @@ const interpolateNumber = ({ input, inputRange, outputRange, options, }) => {
430
485
  };
431
486
  const interpolateString = ({ input, inputRange, outputRange, options, }) => {
432
487
  var _a;
433
- const parsedOutputRange = outputRange.map(parseStringInterpolationValue);
488
+ const initiallyParsedOutputRange = outputRange.map(parseStringInterpolationValue);
489
+ const hasAxisRotation = initiallyParsedOutputRange.some((parsed) => parsed.axisRotation);
490
+ const parsedOutputRange = hasAxisRotation
491
+ ? initiallyParsedOutputRange.map((parsed) => {
492
+ if (parsed.kind !== 'rotate') {
493
+ return parsed;
494
+ }
495
+ if (parsed.axisRotation) {
496
+ return parsed;
497
+ }
498
+ if (parsed.dimensions !== 1) {
499
+ throw new TypeError('Cannot interpolate a multi-angle rotate value with an axis rotation');
500
+ }
501
+ return {
502
+ kind: 'rotate',
503
+ values: [0, 0, 1, parsed.values[0]],
504
+ units: [null, null, null, parsed.units[0]],
505
+ dimensions: 4,
506
+ axisRotation: true,
507
+ };
508
+ })
509
+ : initiallyParsedOutputRange;
434
510
  const kind = (_a = parsedOutputRange[0]) === null || _a === void 0 ? void 0 : _a.kind;
435
511
  if (kind === undefined) {
436
512
  throw new Error('outputRange must have at least 1 element');
@@ -445,9 +521,13 @@ const interpolateString = ({ input, inputRange, outputRange, options, }) => {
445
521
  null,
446
522
  null,
447
523
  null,
524
+ null,
448
525
  ];
449
526
  if (kind !== 'scale') {
450
527
  for (let axis = 0; axis < dimensions; axis++) {
528
+ if (hasAxisRotation && axis < 3) {
529
+ continue;
530
+ }
451
531
  for (const parsed of parsedOutputRange) {
452
532
  const unit = parsed.units[axis];
453
533
  if (unit === null) {
@@ -466,7 +546,7 @@ const interpolateString = ({ input, inputRange, outputRange, options, }) => {
466
546
  }
467
547
  }
468
548
  }
469
- const values = [0, 0, 0];
549
+ const values = [0, 0, 0, 0];
470
550
  for (let axis = 0; axis < dimensions; axis++) {
471
551
  values[axis] = interpolateNumber({
472
552
  input,
@@ -480,6 +560,7 @@ const interpolateString = ({ input, inputRange, outputRange, options, }) => {
480
560
  values,
481
561
  units,
482
562
  dimensions,
563
+ axisRotation: hasAxisRotation,
483
564
  });
484
565
  };
485
566
  const validateTupleOutputRange = (outputRange) => {
@@ -1 +1,4 @@
1
+ export declare const getPortalNodeCurrentScale: () => number;
2
+ export declare const subscribeToPortalNodeCurrentScale: (listener: () => void) => () => void;
3
+ export declare const setPortalNodeCurrentScale: (scale: number) => void;
1
4
  export declare const portalNode: () => HTMLElement;
@@ -1,7 +1,28 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.portalNode = void 0;
3
+ exports.portalNode = exports.setPortalNodeCurrentScale = exports.subscribeToPortalNodeCurrentScale = exports.getPortalNodeCurrentScale = void 0;
4
4
  let _portalNode = null;
5
+ let portalNodeCurrentScale = 1;
6
+ let portalNodeCurrentScaleListeners = [];
7
+ const getPortalNodeCurrentScale = () => portalNodeCurrentScale;
8
+ exports.getPortalNodeCurrentScale = getPortalNodeCurrentScale;
9
+ const subscribeToPortalNodeCurrentScale = (listener) => {
10
+ portalNodeCurrentScaleListeners.push(listener);
11
+ return () => {
12
+ portalNodeCurrentScaleListeners = portalNodeCurrentScaleListeners.filter((currentListener) => currentListener !== listener);
13
+ };
14
+ };
15
+ exports.subscribeToPortalNodeCurrentScale = subscribeToPortalNodeCurrentScale;
16
+ const setPortalNodeCurrentScale = (scale) => {
17
+ if (portalNodeCurrentScale === scale) {
18
+ return;
19
+ }
20
+ portalNodeCurrentScale = scale;
21
+ for (const listener of portalNodeCurrentScaleListeners) {
22
+ listener();
23
+ }
24
+ };
25
+ exports.setPortalNodeCurrentScale = setPortalNodeCurrentScale;
5
26
  const portalNode = () => {
6
27
  if (!_portalNode) {
7
28
  if (typeof document === 'undefined') {
@@ -0,0 +1,13 @@
1
+ import React from 'react';
2
+ export type RenderResourceManager = {
3
+ getOrCreateResource: <T>({ key, create }: {
4
+ key: string;
5
+ create: () => {
6
+ resource: T;
7
+ dispose: () => void;
8
+ };
9
+ }) => T;
10
+ dispose: () => void;
11
+ };
12
+ export declare const makeRenderResourceManager: () => RenderResourceManager;
13
+ export declare const RenderResourceManagerContext: React.Context<RenderResourceManager | null>;