remotion 4.0.532 → 4.0.534

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 (40) hide show
  1. package/dist/cjs/CompositionManager.d.ts +10 -0
  2. package/dist/cjs/CompositionManagerProvider.js +6 -9
  3. package/dist/cjs/HtmlInCanvas.d.ts +2 -0
  4. package/dist/cjs/HtmlInCanvas.js +17 -4
  5. package/dist/cjs/Sequence.d.ts +5 -0
  6. package/dist/cjs/Sequence.js +73 -11
  7. package/dist/cjs/SequenceManager.d.ts +37 -7
  8. package/dist/cjs/SequenceManager.js +317 -30
  9. package/dist/cjs/Track.d.ts +6 -0
  10. package/dist/cjs/Track.js +32 -0
  11. package/dist/cjs/animated-image/AnimatedImage.js +2 -1
  12. package/dist/cjs/canvas-image/CanvasImage.js +2 -1
  13. package/dist/cjs/effects/Solid.js +4 -3
  14. package/dist/cjs/effects/use-memoized-effects.d.ts +3 -1
  15. package/dist/cjs/effects/use-memoized-effects.js +12 -6
  16. package/dist/cjs/evaluate-source-expressions.d.ts +5 -0
  17. package/dist/cjs/evaluate-source-expressions.js +98 -0
  18. package/dist/cjs/freeze.js +6 -8
  19. package/dist/cjs/index.d.ts +2 -0
  20. package/dist/cjs/index.js +3 -1
  21. package/dist/cjs/internals.d.ts +13 -3
  22. package/dist/cjs/internals.js +11 -0
  23. package/dist/cjs/no-react.d.ts +2 -0
  24. package/dist/cjs/no-react.js +3 -0
  25. package/dist/cjs/series/index.js +3 -1
  26. package/dist/cjs/timeline-track-context.d.ts +9 -0
  27. package/dist/cjs/timeline-track-context.js +6 -0
  28. package/dist/cjs/use-media-in-timeline.js +14 -2
  29. package/dist/cjs/use-schema.d.ts +32 -18
  30. package/dist/cjs/use-sequence-registration.js +1 -1
  31. package/dist/cjs/version.d.ts +1 -1
  32. package/dist/cjs/version.js +1 -1
  33. package/dist/cjs/video/html5-video.js +1 -1
  34. package/dist/cjs/with-interactivity-schema.js +13 -7
  35. package/dist/cjs/wrap-remotion-context.d.ts +2 -0
  36. package/dist/cjs/wrap-remotion-context.js +8 -1
  37. package/dist/esm/index.mjs +788 -315
  38. package/dist/esm/no-react.mjs +78 -0
  39. package/dist/esm/version.mjs +1 -1
  40. package/package.json +2 -2
@@ -33,13 +33,14 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.SequenceManagerProvider = exports.VisualModeSettersContext = exports.VisualModeDragOverridesContext = exports.VisualModePropStatusesRefContext = exports.VisualModePropStatusesContext = exports.makeSequencePropsSubscriptionKey = exports.DisableSequenceRegistrationProvider = exports.DisableSequenceRegistrationContext = exports.SequenceRegistrationContext = exports.SequenceManagerRefContext = exports.SequenceManager = void 0;
36
+ exports.SequenceManagerProvider = exports.VisualModeBatchSettersContext = exports.VisualModeSettersContext = exports.useEffectDragOverridesForNodePath = exports.useActiveFromDragOverrideKeys = exports.useDragOverridesForNodePath = exports.VisualModeDragOverridesContext = exports.VisualModePropStatusesRefContext = exports.VisualModePropStatusesContext = exports.makeSequencePropsSubscriptionKey = exports.VisualModeDragOverridesSubscriptionContext = exports.DisableSequenceRegistrationProvider = exports.DisableSequenceRegistrationContext = exports.SequenceRegistrationContext = exports.SequenceManagerRefContext = exports.useSequenceManagerSequences = exports.SequenceManager = exports.SequenceManagerActionsContext = void 0;
37
37
  const jsx_runtime_1 = require("react/jsx-runtime");
38
38
  const react_1 = __importStar(require("react"));
39
39
  const sequence_order_marker_js_1 = require("./sequence-order-marker.js");
40
40
  const use_remotion_environment_js_1 = require("./use-remotion-environment.js");
41
+ const use_sync_external_store_js_1 = require("./use-sync-external-store.js");
41
42
  const useIsomorphicLayoutEffect = typeof window === 'undefined' ? react_1.default.useEffect : react_1.default.useLayoutEffect;
42
- exports.SequenceManager = react_1.default.createContext({
43
+ const defaultSequenceManager = {
43
44
  registerSequence: () => {
44
45
  throw new Error('SequenceManagerContext not initialized');
45
46
  },
@@ -48,7 +49,31 @@ exports.SequenceManager = react_1.default.createContext({
48
49
  throw new Error('SequenceManagerContext not initialized');
49
50
  },
50
51
  sequences: [],
52
+ };
53
+ exports.SequenceManagerActionsContext = react_1.default.createContext({
54
+ registerSequence: defaultSequenceManager.registerSequence,
55
+ updateSequence: defaultSequenceManager.updateSequence,
56
+ unregisterSequence: defaultSequenceManager.unregisterSequence,
57
+ });
58
+ exports.SequenceManager = react_1.default.createContext(defaultSequenceManager);
59
+ const NativeSequenceManagerProvider = exports.SequenceManager.Provider;
60
+ const SequenceManagerProviderWithActions = ({ value, children }) => {
61
+ const actions = (0, react_1.useMemo)(() => ({
62
+ registerSequence: value.registerSequence,
63
+ updateSequence: value.updateSequence,
64
+ unregisterSequence: value.unregisterSequence,
65
+ }), [value.registerSequence, value.updateSequence, value.unregisterSequence]);
66
+ return (jsx_runtime_1.jsx(exports.SequenceManagerActionsContext.Provider, { value: actions, children: jsx_runtime_1.jsx(NativeSequenceManagerProvider, { value: value, children: children }) }));
67
+ };
68
+ // Keep custom SequenceManager.Provider trees in sync with the stable actions
69
+ // context while preserving the legacy reactive sequence-list context.
70
+ Object.defineProperty(exports.SequenceManager, 'Provider', {
71
+ value: SequenceManagerProviderWithActions,
51
72
  });
73
+ const useSequenceManagerSequences = () => {
74
+ return (0, react_1.useContext)(exports.SequenceManager).sequences;
75
+ };
76
+ exports.useSequenceManagerSequences = useSequenceManagerSequences;
52
77
  exports.SequenceManagerRefContext = react_1.default.createContext({
53
78
  current: [],
54
79
  });
@@ -58,6 +83,17 @@ const DisableSequenceRegistrationProvider = ({ children }) => {
58
83
  return react_1.default.createElement(exports.DisableSequenceRegistrationContext.Provider, { value: true }, children);
59
84
  };
60
85
  exports.DisableSequenceRegistrationProvider = DisableSequenceRegistrationProvider;
86
+ exports.VisualModeDragOverridesSubscriptionContext = react_1.default.createContext(null);
87
+ const ActiveFromDragOverrideKeysContext = react_1.default.createContext(null);
88
+ const SequenceManagerScopeProviders = ({ children, dragOverridesSubscription, fromKeys }) => {
89
+ const manager = (0, react_1.useContext)(exports.SequenceManagerActionsContext);
90
+ const scopedDragOverridesSubscription = (0, react_1.useMemo)(() => ({ ...dragOverridesSubscription, manager }), [dragOverridesSubscription, manager]);
91
+ const activeFromDragOverrideKeys = (0, react_1.useMemo)(() => ({ manager, keys: fromKeys }), [fromKeys, manager]);
92
+ return (jsx_runtime_1.jsx(ActiveFromDragOverrideKeysContext.Provider, { value: activeFromDragOverrideKeys, children: jsx_runtime_1.jsx(exports.VisualModeDragOverridesSubscriptionContext.Provider, { value: scopedDragOverridesSubscription, children: children }) }));
93
+ };
94
+ const emptyDragOverrides = {};
95
+ const emptyFromOverrideKeys = new Set();
96
+ const emptyEffectDragOverrides = {};
61
97
  const makeSequencePropsSubscriptionKey = (key) => {
62
98
  return `${key.absolutePath}\0${key.nodePath.join('.')}\0${key.sequenceKeys.join('.')}\0${key.effectKeys.map((keys) => keys.join('.')).join('.')}`;
63
99
  };
@@ -76,6 +112,67 @@ exports.VisualModeDragOverridesContext = react_1.default.createContext({
76
112
  throw new Error('VisualModeDragOverridesContext not initialized');
77
113
  },
78
114
  });
115
+ /* eslint-disable react-hooks/rules-of-hooks */
116
+ const useDragOverridesForNodePath = (nodePath) => {
117
+ const subscription = (0, react_1.useContext)(exports.VisualModeDragOverridesSubscriptionContext);
118
+ const manager = (0, react_1.useContext)(exports.SequenceManagerActionsContext);
119
+ const scopedSubscription = (subscription === null || subscription === void 0 ? void 0 : subscription.manager) === manager ? subscription : null;
120
+ // Legacy providers only supply VisualModeDragOverridesContext. Its presence is
121
+ // fixed for the lifetime of a mounted tree.
122
+ const legacy = scopedSubscription === null
123
+ ? (0, react_1.useContext)(exports.VisualModeDragOverridesContext)
124
+ : null;
125
+ const key = nodePath === null ? null : (0, exports.makeSequencePropsSubscriptionKey)(nodePath);
126
+ const subscribe = (0, react_1.useCallback)((listener) => {
127
+ var _a;
128
+ return (_a = scopedSubscription === null || scopedSubscription === void 0 ? void 0 : scopedSubscription.subscribe(key, listener)) !== null && _a !== void 0 ? _a : (() => undefined);
129
+ }, [key, scopedSubscription]);
130
+ const getSnapshot = (0, react_1.useCallback)(() => {
131
+ var _a;
132
+ return (_a = scopedSubscription === null || scopedSubscription === void 0 ? void 0 : scopedSubscription.getSnapshot(key)) !== null && _a !== void 0 ? _a : emptyDragOverrides;
133
+ }, [key, scopedSubscription]);
134
+ const overrides = (0, use_sync_external_store_js_1.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
135
+ return legacy !== null && nodePath !== null
136
+ ? legacy.getDragOverrides(nodePath)
137
+ : overrides;
138
+ };
139
+ exports.useDragOverridesForNodePath = useDragOverridesForNodePath;
140
+ const useActiveFromDragOverrideKeys = () => {
141
+ const snapshot = (0, react_1.useContext)(ActiveFromDragOverrideKeysContext);
142
+ const manager = (0, react_1.useContext)(exports.SequenceManagerActionsContext);
143
+ return (snapshot === null || snapshot === void 0 ? void 0 : snapshot.manager) === manager ? snapshot.keys : emptyFromOverrideKeys;
144
+ };
145
+ exports.useActiveFromDragOverrideKeys = useActiveFromDragOverrideKeys;
146
+ const useEffectDragOverridesForNodePath = (nodePath, effectCount) => {
147
+ const subscription = (0, react_1.useContext)(exports.VisualModeDragOverridesSubscriptionContext);
148
+ const manager = (0, react_1.useContext)(exports.SequenceManagerActionsContext);
149
+ const scopedSubscription = (subscription === null || subscription === void 0 ? void 0 : subscription.manager) === manager ? subscription : null;
150
+ // Legacy providers only supply VisualModeDragOverridesContext. Its presence is
151
+ // fixed for the lifetime of a mounted tree.
152
+ const legacy = scopedSubscription === null
153
+ ? (0, react_1.useContext)(exports.VisualModeDragOverridesContext)
154
+ : null;
155
+ const key = nodePath === null ? null : (0, exports.makeSequencePropsSubscriptionKey)(nodePath);
156
+ const subscribe = (0, react_1.useCallback)((listener) => {
157
+ var _a;
158
+ return (_a = scopedSubscription === null || scopedSubscription === void 0 ? void 0 : scopedSubscription.subscribeEffects(key, listener)) !== null && _a !== void 0 ? _a : (() => undefined);
159
+ }, [key, scopedSubscription]);
160
+ const getSnapshot = (0, react_1.useCallback)(() => {
161
+ var _a;
162
+ return (_a = scopedSubscription === null || scopedSubscription === void 0 ? void 0 : scopedSubscription.getEffectSnapshot(key)) !== null && _a !== void 0 ? _a : emptyEffectDragOverrides;
163
+ }, [key, scopedSubscription]);
164
+ const overrides = (0, use_sync_external_store_js_1.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
165
+ if (legacy !== null && nodePath !== null) {
166
+ const legacyOverrides = {};
167
+ for (let index = 0; index < effectCount; index++) {
168
+ legacyOverrides[index] = legacy.getEffectDragOverrides(nodePath, index);
169
+ }
170
+ return legacyOverrides;
171
+ }
172
+ return overrides;
173
+ };
174
+ exports.useEffectDragOverridesForNodePath = useEffectDragOverridesForNodePath;
175
+ /* eslint-enable react-hooks/rules-of-hooks */
79
176
  exports.VisualModeSettersContext = react_1.default.createContext({
80
177
  setDragOverrides: () => {
81
178
  throw new Error('VisualModeSettersContext not initialized');
@@ -96,6 +193,7 @@ exports.VisualModeSettersContext = react_1.default.createContext({
96
193
  throw new Error('VisualModeSettersContext not initialized');
97
194
  },
98
195
  });
196
+ exports.VisualModeBatchSettersContext = react_1.default.createContext(null);
99
197
  const effectDragOverridesKey = (nodePath, effectIndex) => `${(0, exports.makeSequencePropsSubscriptionKey)(nodePath)}.effects.${effectIndex}`;
100
198
  const SequenceManagerProvider = ({ children }) => {
101
199
  const { isStudio } = (0, use_remotion_environment_js_1.useRemotionEnvironment)();
@@ -105,45 +203,202 @@ const SequenceManagerProvider = ({ children }) => {
105
203
  const [sequences, setSequences] = (0, react_1.useState)([]);
106
204
  const sequencesRef = (0, react_1.useRef)(sequences);
107
205
  sequencesRef.current = sequences;
108
- const [dragOverrides, setControlOverrides] = (0, react_1.useState)({});
109
- const controlOverridesRef = (0, react_1.useRef)(dragOverrides);
110
- controlOverridesRef.current = dragOverrides;
206
+ const [dragOverrideState, setDragOverrideState] = (0, react_1.useState)(() => ({
207
+ overrides: {},
208
+ fromKeys: new Set(),
209
+ }));
210
+ const dragOverrides = dragOverrideState.overrides;
211
+ const dragOverridesStore = (0, react_1.useRef)({
212
+ snapshot: dragOverrides,
213
+ listeners: new Map(),
214
+ });
111
215
  const [effectDragOverridesState, setEffectDragOverridesState] = (0, react_1.useState)({});
216
+ const effectDragOverridesStore = (0, react_1.useRef)({
217
+ snapshot: effectDragOverridesState,
218
+ byNode: new Map(),
219
+ listeners: new Map(),
220
+ });
112
221
  const [propStatuses, setPropStatusesMapState] = (0, react_1.useState)({});
113
222
  const propStatusesRef = (0, react_1.useRef)(propStatuses);
114
223
  propStatusesRef.current = propStatuses;
115
- const setDragOverrides = (0, react_1.useCallback)((nodePath, key, value) => {
116
- setControlOverrides((prev) => ({
117
- ...prev,
118
- [(0, exports.makeSequencePropsSubscriptionKey)(nodePath)]: {
119
- ...prev[(0, exports.makeSequencePropsSubscriptionKey)(nodePath)],
120
- [key]: value,
121
- },
122
- }));
224
+ const setDragOverridesBatch = (0, react_1.useCallback)((overrides) => {
225
+ setDragOverrideState((prevState) => {
226
+ var _a;
227
+ const prev = prevState.overrides;
228
+ let next = null;
229
+ let nextFromKeys = prevState.fromKeys;
230
+ for (const { nodePath, key, value } of overrides) {
231
+ const mapKey = (0, exports.makeSequencePropsSubscriptionKey)(nodePath);
232
+ const existing = (_a = (next !== null && next !== void 0 ? next : prev)[mapKey]) === null || _a === void 0 ? void 0 : _a[key];
233
+ if (existing === value ||
234
+ ((existing === null || existing === void 0 ? void 0 : existing.type) === 'static' &&
235
+ value.type === 'static' &&
236
+ Object.is(existing.value, value.value))) {
237
+ continue;
238
+ }
239
+ if (next === null) {
240
+ next = { ...prev };
241
+ }
242
+ if (next[mapKey] === prev[mapKey]) {
243
+ next[mapKey] = { ...prev[mapKey] };
244
+ }
245
+ next[mapKey][key] = value;
246
+ if (key === 'from' && !nextFromKeys.has(mapKey)) {
247
+ nextFromKeys = new Set(nextFromKeys);
248
+ nextFromKeys.add(mapKey);
249
+ }
250
+ }
251
+ return next === null
252
+ ? prevState
253
+ : { overrides: next, fromKeys: nextFromKeys };
254
+ });
255
+ }, []);
256
+ const setDragOverrides = (0, react_1.useCallback)((nodePath, key, value) => setDragOverridesBatch([{ nodePath, key, value }]), [setDragOverridesBatch]);
257
+ const subscribeDragOverrides = (0, react_1.useCallback)((key, listener) => {
258
+ if (key === null) {
259
+ return () => undefined;
260
+ }
261
+ let listeners = dragOverridesStore.current.listeners.get(key);
262
+ if (!listeners) {
263
+ listeners = new Set();
264
+ dragOverridesStore.current.listeners.set(key, listeners);
265
+ }
266
+ listeners.add(listener);
267
+ return () => {
268
+ listeners.delete(listener);
269
+ if (listeners.size === 0) {
270
+ dragOverridesStore.current.listeners.delete(key);
271
+ }
272
+ };
273
+ }, []);
274
+ const getDragOverridesSnapshot = (0, react_1.useCallback)((key) => {
275
+ var _a;
276
+ return key === null
277
+ ? emptyDragOverrides
278
+ : ((_a = dragOverridesStore.current.snapshot[key]) !== null && _a !== void 0 ? _a : emptyDragOverrides);
279
+ }, []);
280
+ useIsomorphicLayoutEffect(() => {
281
+ var _a;
282
+ const previous = dragOverridesStore.current.snapshot;
283
+ dragOverridesStore.current.snapshot = dragOverrides;
284
+ for (const key of new Set([
285
+ ...Object.keys(previous),
286
+ ...Object.keys(dragOverrides),
287
+ ])) {
288
+ if (previous[key] !== dragOverrides[key]) {
289
+ for (const listener of (_a = dragOverridesStore.current.listeners.get(key)) !== null && _a !== void 0 ? _a : []) {
290
+ listener();
291
+ }
292
+ }
293
+ }
294
+ }, [dragOverrides]);
295
+ const subscribeEffectDragOverrides = (0, react_1.useCallback)((key, listener) => {
296
+ if (key === null) {
297
+ return () => undefined;
298
+ }
299
+ let listeners = effectDragOverridesStore.current.listeners.get(key);
300
+ if (!listeners) {
301
+ listeners = new Set();
302
+ effectDragOverridesStore.current.listeners.set(key, listeners);
303
+ }
304
+ listeners.add(listener);
305
+ return () => {
306
+ listeners.delete(listener);
307
+ if (listeners.size === 0) {
308
+ effectDragOverridesStore.current.listeners.delete(key);
309
+ }
310
+ };
311
+ }, []);
312
+ const getEffectDragOverridesSnapshot = (0, react_1.useCallback)((key) => {
313
+ var _a;
314
+ return key === null
315
+ ? emptyEffectDragOverrides
316
+ : ((_a = effectDragOverridesStore.current.byNode.get(key)) !== null && _a !== void 0 ? _a : emptyEffectDragOverrides);
123
317
  }, []);
318
+ useIsomorphicLayoutEffect(() => {
319
+ var _a;
320
+ const previous = effectDragOverridesStore.current.snapshot;
321
+ const byNode = new Map(effectDragOverridesStore.current.byNode);
322
+ const changedNodes = new Set();
323
+ for (const flatKey of new Set([
324
+ ...Object.keys(previous),
325
+ ...Object.keys(effectDragOverridesState),
326
+ ])) {
327
+ if (previous[flatKey] === effectDragOverridesState[flatKey]) {
328
+ continue;
329
+ }
330
+ const separator = flatKey.lastIndexOf('.effects.');
331
+ if (separator === -1) {
332
+ throw new Error('Invalid effect drag override key');
333
+ }
334
+ const nodeKey = flatKey.slice(0, separator);
335
+ const effectIndex = flatKey.slice(separator + '.effects.'.length);
336
+ if (!changedNodes.has(nodeKey)) {
337
+ byNode.set(nodeKey, { ...byNode.get(nodeKey) });
338
+ changedNodes.add(nodeKey);
339
+ }
340
+ const next = byNode.get(nodeKey);
341
+ if (effectDragOverridesState[flatKey] === undefined) {
342
+ delete next[effectIndex];
343
+ }
344
+ else {
345
+ next[effectIndex] = effectDragOverridesState[flatKey];
346
+ }
347
+ }
348
+ for (const nodeKey of changedNodes) {
349
+ if (Object.keys(byNode.get(nodeKey)).length === 0) {
350
+ byNode.delete(nodeKey);
351
+ }
352
+ }
353
+ effectDragOverridesStore.current.snapshot = effectDragOverridesState;
354
+ effectDragOverridesStore.current.byNode = byNode;
355
+ for (const nodeKey of changedNodes) {
356
+ for (const listener of (_a = effectDragOverridesStore.current.listeners.get(nodeKey)) !== null && _a !== void 0 ? _a : []) {
357
+ listener();
358
+ }
359
+ }
360
+ }, [effectDragOverridesState]);
124
361
  const clearDragOverrides = (0, react_1.useCallback)((nodePath) => {
125
- setControlOverrides((prev) => {
362
+ setDragOverrideState((prevState) => {
363
+ const prev = prevState.overrides;
126
364
  const key = (0, exports.makeSequencePropsSubscriptionKey)(nodePath);
127
365
  if (!prev[key]) {
128
- return prev;
366
+ return prevState;
129
367
  }
130
368
  const next = { ...prev };
131
369
  delete next[key];
132
- return next;
370
+ const nextFromKeys = prevState.fromKeys.has(key)
371
+ ? new Set(prevState.fromKeys)
372
+ : prevState.fromKeys;
373
+ nextFromKeys.delete(key);
374
+ return { overrides: next, fromKeys: nextFromKeys };
133
375
  });
134
376
  }, []);
135
- const setEffectDragOverrides = (0, react_1.useCallback)((nodePath, effectIndex, key, value) => {
377
+ const setEffectDragOverridesBatch = (0, react_1.useCallback)((overrides) => {
136
378
  setEffectDragOverridesState((prev) => {
137
- const mapKey = effectDragOverridesKey(nodePath, effectIndex);
138
- return {
139
- ...prev,
140
- [mapKey]: {
141
- ...prev[mapKey],
142
- [key]: value,
143
- },
144
- };
379
+ var _a;
380
+ let next = null;
381
+ for (const { nodePath, effectIndex, key, value } of overrides) {
382
+ const mapKey = effectDragOverridesKey(nodePath, effectIndex);
383
+ const existing = (_a = (next !== null && next !== void 0 ? next : prev)[mapKey]) === null || _a === void 0 ? void 0 : _a[key];
384
+ if (existing === value ||
385
+ ((existing === null || existing === void 0 ? void 0 : existing.type) === 'static' &&
386
+ value.type === 'static' &&
387
+ Object.is(existing.value, value.value))) {
388
+ continue;
389
+ }
390
+ if (next === null) {
391
+ next = { ...prev };
392
+ }
393
+ if (next[mapKey] === prev[mapKey]) {
394
+ next[mapKey] = { ...prev[mapKey] };
395
+ }
396
+ next[mapKey][key] = value;
397
+ }
398
+ return next !== null && next !== void 0 ? next : prev;
145
399
  });
146
400
  }, []);
401
+ const setEffectDragOverrides = (0, react_1.useCallback)((nodePath, effectIndex, key, value) => setEffectDragOverridesBatch([{ nodePath, effectIndex, key, value }]), [setEffectDragOverridesBatch]);
147
402
  const clearEffectDragOverrides = (0, react_1.useCallback)((nodePath, effectIndex) => {
148
403
  setEffectDragOverridesState((prev) => {
149
404
  const mapKey = effectDragOverridesKey(nodePath, effectIndex);
@@ -250,11 +505,31 @@ const SequenceManagerProvider = ({ children }) => {
250
505
  if (index === -1) {
251
506
  return seqs;
252
507
  }
508
+ const previousSequence = seqs[index];
509
+ const timelineOrder = (_b = (_a = committedOrderRef.current) === null || _a === void 0 ? void 0 : _a.get(seq.id)) !== null && _b !== void 0 ? _b : null;
510
+ // A new registration getter does not necessarily change the metadata.
511
+ let unchanged = Object.is(previousSequence.timelineOrder, timelineOrder);
512
+ // The manager adds timelineOrder even if the incoming object omits it.
513
+ let keyCount = 1;
514
+ if (unchanged) {
515
+ for (const key in seq) {
516
+ if (key === 'timelineOrder' ||
517
+ !Object.prototype.hasOwnProperty.call(seq, key)) {
518
+ continue;
519
+ }
520
+ keyCount++;
521
+ if (!Object.prototype.hasOwnProperty.call(previousSequence, key) ||
522
+ !Object.is(previousSequence[key], seq[key])) {
523
+ unchanged = false;
524
+ break;
525
+ }
526
+ }
527
+ }
528
+ if (unchanged && Object.keys(previousSequence).length === keyCount) {
529
+ return seqs;
530
+ }
253
531
  const next = [...seqs];
254
- next[index] = {
255
- ...seq,
256
- timelineOrder: (_b = (_a = committedOrderRef.current) === null || _a === void 0 ? void 0 : _a.get(seq.id)) !== null && _b !== void 0 ? _b : null,
257
- };
532
+ next[index] = { ...seq, timelineOrder };
258
533
  return next;
259
534
  });
260
535
  }, []);
@@ -269,6 +544,17 @@ const SequenceManagerProvider = ({ children }) => {
269
544
  unregisterSequence,
270
545
  };
271
546
  }, [registerSequence, sequences, unregisterSequence, updateSequence]);
547
+ const dragOverridesSubscription = (0, react_1.useMemo)(() => ({
548
+ subscribe: subscribeDragOverrides,
549
+ getSnapshot: getDragOverridesSnapshot,
550
+ subscribeEffects: subscribeEffectDragOverrides,
551
+ getEffectSnapshot: getEffectDragOverridesSnapshot,
552
+ }), [
553
+ getDragOverridesSnapshot,
554
+ getEffectDragOverridesSnapshot,
555
+ subscribeDragOverrides,
556
+ subscribeEffectDragOverrides,
557
+ ]);
272
558
  const getDragOverrides = (0, react_1.useCallback)((nodePath) => {
273
559
  var _a;
274
560
  return (_a = dragOverrides[(0, exports.makeSequencePropsSubscriptionKey)(nodePath)]) !== null && _a !== void 0 ? _a : {};
@@ -305,7 +591,8 @@ const SequenceManagerProvider = ({ children }) => {
305
591
  setPropStatuses,
306
592
  remapPropStatuses,
307
593
  ]);
308
- const providers = (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 }) }) }) }) }) }));
594
+ const batchSettersContext = (0, react_1.useMemo)(() => ({ setDragOverridesBatch, setEffectDragOverridesBatch }), [setDragOverridesBatch, setEffectDragOverridesBatch]);
595
+ const providers = (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(SequenceManagerScopeProviders, { dragOverridesSubscription: dragOverridesSubscription, fromKeys: dragOverrideState.fromKeys, children: jsx_runtime_1.jsx(exports.VisualModeDragOverridesContext.Provider, { value: dragOverridesContext, children: jsx_runtime_1.jsx(exports.VisualModeSettersContext.Provider, { value: settersContext, children: jsx_runtime_1.jsx(exports.VisualModeBatchSettersContext.Provider, { value: batchSettersContext, children: children }) }) }) }) }) }) }) }));
309
596
  return isStudio ? (jsx_runtime_1.jsx(sequence_order_marker_js_1.SequenceManagerOrderMarker, { managerId: sequenceManagerId, children: providers })) : (providers);
310
597
  };
311
598
  exports.SequenceManagerProvider = SequenceManagerProvider;
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ import { type SequenceProps } from './Sequence.js';
3
+ export type TrackProps = Pick<SequenceProps, 'children' | 'name' | 'from' | 'durationInFrames' | 'hidden' | 'showInTimeline'>;
4
+ export declare const TrackWithoutSchema: React.FC<SequenceProps>;
5
+ /** Groups clips on one Studio timeline row and applies Sequence timing. */
6
+ export declare const Track: React.ComponentType<TrackProps>;
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Track = exports.TrackWithoutSchema = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const enable_sequence_stack_traces_js_1 = require("./enable-sequence-stack-traces.js");
7
+ const interactivity_schema_js_1 = require("./interactivity-schema.js");
8
+ const Sequence_js_1 = require("./Sequence.js");
9
+ const timeline_track_context_js_1 = require("./timeline-track-context.js");
10
+ const with_interactivity_schema_js_1 = require("./with-interactivity-schema.js");
11
+ const trackSchema = {
12
+ name: interactivity_schema_js_1.sequenceSchema.name,
13
+ hidden: interactivity_schema_js_1.sequenceSchema.hidden,
14
+ };
15
+ // Series variants share the Track foundation while retaining their own
16
+ // Sequence props, layout defaults, and interactivity schemas.
17
+ const TrackWithoutSchema = ({ name = 'Track', children, layout = 'none', ...props }) => {
18
+ const [id] = (0, react_1.useState)(() => String(Math.random()));
19
+ const tracksEnabled = (0, react_1.useContext)(timeline_track_context_js_1.ExperimentalTracksEnabledContext);
20
+ const value = (0, react_1.useMemo)(() => (tracksEnabled ? { id, name } : null), [id, name, tracksEnabled]);
21
+ return (jsx_runtime_1.jsx(timeline_track_context_js_1.TimelineTrackContext.Provider, { value: value, children: jsx_runtime_1.jsx(Sequence_js_1.SequenceWithoutSchema, { ...props, name: name, layout: layout, _remotionInternalTimelineTrack: { role: 'track' }, children: children }) }));
22
+ };
23
+ exports.TrackWithoutSchema = TrackWithoutSchema;
24
+ /** Groups clips on one Studio timeline row and applies Sequence timing. */
25
+ exports.Track = (0, with_interactivity_schema_js_1.withInteractivitySchema)({
26
+ Component: exports.TrackWithoutSchema,
27
+ componentName: '<Track>',
28
+ componentIdentity: 'dev.remotion.remotion.Track',
29
+ schema: trackSchema,
30
+ supportsEffects: false,
31
+ });
32
+ (0, enable_sequence_stack_traces_js_1.addSequenceStackTraces)(exports.Track);
@@ -52,7 +52,7 @@ const getCanvasPropsFromSequenceProps = (props) => {
52
52
  return canvasProps;
53
53
  };
54
54
  const AnimatedImageContent = (0, react_2.forwardRef)(({ src, width, height, onError, loopBehavior = 'loop', playbackRate = 1, fit = 'fill', requestInit, effects, controls, ...props }, canvasRef) => {
55
- var _a;
55
+ var _a, _b;
56
56
  const resolvedSrc = (0, resolve_image_source_1.resolveAnimatedImageSource)(src);
57
57
  const [imageDecoder, setImageDecoder] = (0, react_2.useState)(null);
58
58
  const { delayRender, continueRender } = (0, use_delay_render_js_1.useDelayRender)();
@@ -69,6 +69,7 @@ const AnimatedImageContent = (0, react_2.forwardRef)(({ src, width, height, onEr
69
69
  const memoizedEffects = (0, use_memoized_effects_js_1.useMemoizedEffects)({
70
70
  effects,
71
71
  overrideId: (_a = controls === null || controls === void 0 ? void 0 : controls.overrideId) !== null && _a !== void 0 ? _a : null,
72
+ videoConfigValues: (_b = controls === null || controls === void 0 ? void 0 : controls.videoConfigValues) !== null && _b !== void 0 ? _b : null,
72
73
  });
73
74
  (0, react_2.useImperativeHandle)(canvasRef, () => {
74
75
  var _a;
@@ -111,7 +111,7 @@ const waitForNextFrame = ({ onFrame, }) => {
111
111
  return () => cancelAnimationFrame(frame);
112
112
  };
113
113
  const CanvasImageContent = (0, react_1.forwardRef)(({ src, crossOrigin, width, height, fit = 'fill', effects, controls, onError, className, style, id, pauseWhenLoading, maxRetries = 2, delayRenderRetries, delayRenderTimeoutInMilliseconds, ...canvasProps }, ref) => {
114
- var _a;
114
+ var _a, _b;
115
115
  const { delayRender, continueRender, cancelRender } = (0, use_delay_render_js_1.useDelayRender)();
116
116
  const { delayPlayback } = (0, use_buffer_state_js_1.useBufferState)();
117
117
  const [outputCanvas, setOutputCanvas] = (0, react_1.useState)(null);
@@ -121,6 +121,7 @@ const CanvasImageContent = (0, react_1.forwardRef)(({ src, crossOrigin, width, h
121
121
  const memoizedEffects = (0, use_memoized_effects_js_1.useMemoizedEffects)({
122
122
  effects,
123
123
  overrideId: (_a = controls === null || controls === void 0 ? void 0 : controls.overrideId) !== null && _a !== void 0 ? _a : null,
124
+ videoConfigValues: (_b = controls === null || controls === void 0 ? void 0 : controls.videoConfigValues) !== null && _b !== void 0 ? _b : null,
124
125
  });
125
126
  const sequenceContext = (0, react_1.useContext)(SequenceContext_js_1.SequenceContext);
126
127
  const pendingLoadDelayRef = (0, react_1.useRef)(null);
@@ -65,7 +65,7 @@ exports.solidSchema = {
65
65
  ...interactivity_schema_js_1.borderRadiusSchema,
66
66
  ...interactivity_schema_js_1.cropSchema,
67
67
  };
68
- const SolidInner = ({ color, width, height, effects = [], className, style, pixelDensity, overrideId, reference, }) => {
68
+ const SolidInner = ({ color, width, height, effects = [], className, style, pixelDensity, overrideId, videoConfigValues, reference, }) => {
69
69
  const { delayRender, continueRender, cancelRender } = (0, use_delay_render_js_1.useDelayRender)();
70
70
  const resolvedPixelDensity = resolveSolidPixelDensity(pixelDensity);
71
71
  const canvasWidth = Math.ceil(width * resolvedPixelDensity);
@@ -74,6 +74,7 @@ const SolidInner = ({ color, width, height, effects = [], className, style, pixe
74
74
  const memoizedEffects = (0, use_memoized_effects_js_1.useMemoizedEffects)({
75
75
  effects,
76
76
  overrideId: overrideId !== null && overrideId !== void 0 ? overrideId : null,
77
+ videoConfigValues,
77
78
  });
78
79
  const sourceCanvas = (0, react_1.useMemo)(() => {
79
80
  if (typeof document === 'undefined') {
@@ -157,7 +158,7 @@ const SolidInner = ({ color, width, height, effects = [], className, style, pixe
157
158
  return (jsx_runtime_1.jsx("canvas", { ref: canvasRef, width: canvasWidth, height: canvasHeight, className: className, style: canvasStyle }));
158
159
  };
159
160
  const SolidOuter = (0, react_1.forwardRef)(({ effects = [], controls, color, height, width, className, durationInFrames, style, name, from, premountFor, postmountFor, styleWhilePremounted, styleWhilePostmounted, trimBefore, playbackRate, loop, freeze, hidden, showInTimeline, pixelDensity, cropLeft, cropRight, cropTop, cropBottom, ...props }, ref) => {
160
- var _a;
161
+ var _a, _b;
161
162
  props;
162
163
  const memoizedEffectDefinitions = (0, use_memoized_effects_js_1.useMemoizedEffectDefinitions)(effects);
163
164
  const actualRef = (0, react_1.useRef)(null);
@@ -186,7 +187,7 @@ const SolidOuter = (0, react_1.forwardRef)(({ effects = [], controls, color, hei
186
187
  style: premountingStyle,
187
188
  componentName: '<Solid />',
188
189
  });
189
- return (jsx_runtime_1.jsx(freeze_js_1.Freeze, { frame: freezeFrame, active: isPremountingOrPostmounting, _remotionInternalIsPremounting: premountingActive, children: jsx_runtime_1.jsx(Sequence_js_1.Sequence, { layout: "none", from: from, trimBefore: trimBefore, playbackRate: playbackRate, loop: loop, freeze: freeze, hidden: hidden, showInTimeline: showInTimeline, controls: controls, _remotionInternalEffects: memoizedEffectDefinitions, durationInFrames: durationInFrames, name: name !== null && name !== void 0 ? name : '<Solid>', _remotionInternalDocumentationLink: "https://www.remotion.dev/docs/solid", ...props, _remotionInternalPremountDisplay: effectivePremountFor || null, _remotionInternalPostmountDisplay: effectivePostmountFor || null, _remotionInternalIsPremounting: premountingActive, _remotionInternalIsPostmounting: postmountingActive, children: 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: croppedStyle !== null && croppedStyle !== void 0 ? croppedStyle : undefined, effects: effects, pixelDensity: pixelDensity }) }) }));
190
+ return (jsx_runtime_1.jsx(freeze_js_1.Freeze, { frame: freezeFrame, active: isPremountingOrPostmounting, _remotionInternalIsPremounting: premountingActive, children: jsx_runtime_1.jsx(Sequence_js_1.Sequence, { layout: "none", from: from, trimBefore: trimBefore, playbackRate: playbackRate, loop: loop, freeze: freeze, hidden: hidden, showInTimeline: showInTimeline, controls: controls, _remotionInternalEffects: memoizedEffectDefinitions, durationInFrames: durationInFrames, name: name !== null && name !== void 0 ? name : '<Solid>', _remotionInternalDocumentationLink: "https://www.remotion.dev/docs/solid", ...props, _remotionInternalPremountDisplay: effectivePremountFor || null, _remotionInternalPostmountDisplay: effectivePostmountFor || null, _remotionInternalIsPremounting: premountingActive, _remotionInternalIsPostmounting: postmountingActive, children: jsx_runtime_1.jsx(SolidInner, { reference: actualRef, videoConfigValues: (_a = controls === null || controls === void 0 ? void 0 : controls.videoConfigValues) !== null && _a !== void 0 ? _a : null, overrideId: (_b = controls === null || controls === void 0 ? void 0 : controls.overrideId) !== null && _b !== void 0 ? _b : null, color: color, height: height, width: width, className: className, style: croppedStyle !== null && croppedStyle !== void 0 ? croppedStyle : undefined, effects: effects, pixelDensity: pixelDensity }) }) }));
190
191
  });
191
192
  exports.Solid = (0, with_interactivity_schema_js_1.withInteractivitySchema)({
192
193
  Component: SolidOuter,
@@ -2,6 +2,7 @@ import type { RuntimeValueStore } from '../runtime-value-store.js';
2
2
  import type { CannotUpdateEffectReason, CannotUpdateSequenceReason } from '../SequenceManager.js';
3
3
  import { type SequencePropsSubscriptionKey } from '../SequenceManager.js';
4
4
  import { type CanUpdateSequencePropStatus, type PropStatuses } from '../use-schema.js';
5
+ import type { VideoConfigValues } from '../video-config.js';
5
6
  import type { EffectDefinitionAndStack, EffectDescriptor, EffectDefinition } from './effect-types.js';
6
7
  export declare const useMemoizedEffectDefinitions: (effects: readonly EffectDescriptor<unknown>[]) => readonly EffectDefinition<unknown>[] & {
7
8
  readonly runtimeValues: readonly RuntimeValueStore[];
@@ -23,8 +24,9 @@ export declare const getEffectPropStatusesCtx: ({ propStatuses, nodePath, effect
23
24
  }) => EffectStatus;
24
25
  export declare const getPropStatusesCtx: (propStatuses: PropStatuses, nodePath: SequencePropsSubscriptionKey) => Record<string, CanUpdateSequencePropStatus> | undefined;
25
26
  export type GetPropStatusesType = typeof getPropStatusesCtx;
26
- export declare const useMemoizedEffects: ({ effects, overrideId, }: {
27
+ export declare const useMemoizedEffects: ({ effects, overrideId, videoConfigValues, }: {
27
28
  effects: readonly EffectDescriptor<unknown>[];
28
29
  readonly overrideId: string | null;
30
+ videoConfigValues: VideoConfigValues | null;
29
31
  }) => EffectDefinitionAndStack<unknown>[];
30
32
  export {};
@@ -2,12 +2,14 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useMemoizedEffects = exports.getPropStatusesCtx = exports.getEffectPropStatusesCtx = exports.useMemoizedEffectDefinitions = void 0;
4
4
  const react_1 = require("react");
5
+ const evaluate_source_expressions_js_1 = require("../evaluate-source-expressions.js");
5
6
  const get_effective_visual_mode_value_js_1 = require("../get-effective-visual-mode-value.js");
6
7
  const interpolate_keyframed_status_js_1 = require("../interpolate-keyframed-status.js");
7
8
  const runtime_value_store_js_1 = require("../runtime-value-store.js");
8
9
  const sequence_node_path_js_1 = require("../sequence-node-path.js");
9
10
  const SequenceManager_js_1 = require("../SequenceManager.js");
10
11
  const use_current_frame_js_1 = require("../use-current-frame.js");
12
+ const emptyDragOverrides = {};
11
13
  const mergeOverrides = ({ descriptor, propStatusOverrides, dragOverrides, frame, }) => {
12
14
  if (!propStatusOverrides && !dragOverrides) {
13
15
  return { params: descriptor.params, effectKey: descriptor.effectKey };
@@ -105,7 +107,10 @@ const getEffectPropStatusesCtx = ({ propStatuses, nodePath, effectIndex, }) => {
105
107
  if (!effect.canUpdate) {
106
108
  return { type: 'cannot-update-effect', reason: effect.reason };
107
109
  }
108
- return { type: 'can-update-effect', props: effect.props };
110
+ return {
111
+ type: 'can-update-effect',
112
+ props: (0, evaluate_source_expressions_js_1.evaluateSourcePropStatuses)(effect.props, nodePath.videoConfigValues),
113
+ };
109
114
  };
110
115
  exports.getEffectPropStatusesCtx = getEffectPropStatusesCtx;
111
116
  const getPropStatusesCtx = (propStatuses, nodePath) => {
@@ -116,21 +121,22 @@ const getPropStatusesCtx = (propStatuses, nodePath) => {
116
121
  if (!status.canUpdate) {
117
122
  return undefined;
118
123
  }
119
- return status.props;
124
+ return (0, evaluate_source_expressions_js_1.evaluateSourcePropStatuses)(status.props, nodePath.videoConfigValues);
120
125
  };
121
126
  exports.getPropStatusesCtx = getPropStatusesCtx;
122
- const useMemoizedEffects = ({ effects, overrideId, }) => {
127
+ const useMemoizedEffects = ({ effects, overrideId, videoConfigValues, }) => {
123
128
  var _a;
124
129
  const previousRef = (0, react_1.useRef)(null);
125
130
  const { propStatuses } = (0, react_1.useContext)(SequenceManager_js_1.VisualModePropStatusesContext);
126
- const { getEffectDragOverrides } = (0, react_1.useContext)(SequenceManager_js_1.VisualModeDragOverridesContext);
127
131
  const frame = (0, use_current_frame_js_1.useCurrentFrame)();
128
132
  const { overrideIdToNodePathMappings } = (0, react_1.useContext)(sequence_node_path_js_1.OverrideIdsToNodePathsGettersContext);
129
133
  const previous = previousRef.current;
130
134
  const nodePath = overrideId
131
135
  ? ((_a = overrideIdToNodePathMappings[overrideId]) !== null && _a !== void 0 ? _a : null)
132
136
  : null;
137
+ const effectDragOverrides = (0, SequenceManager_js_1.useEffectDragOverridesForNodePath)(nodePath, effects.length);
133
138
  const resolved = effects.map((descriptor, index) => {
139
+ var _a;
134
140
  if (nodePath === null) {
135
141
  return {
136
142
  descriptor,
@@ -140,13 +146,13 @@ const useMemoizedEffects = ({ effects, overrideId, }) => {
140
146
  }
141
147
  const effectStatus = (0, exports.getEffectPropStatusesCtx)({
142
148
  propStatuses,
143
- nodePath,
149
+ nodePath: { ...nodePath, videoConfigValues },
144
150
  effectIndex: index,
145
151
  });
146
152
  const propStatusOverrides = effectStatus.type === 'can-update-effect'
147
153
  ? resolvePropStatusOverrides(effectStatus.props, frame)
148
154
  : null;
149
- const dragOverridesMap = getEffectDragOverrides(nodePath, index);
155
+ const dragOverridesMap = (_a = effectDragOverrides[index]) !== null && _a !== void 0 ? _a : emptyDragOverrides;
150
156
  const dragOverrides = Object.keys(dragOverridesMap).length === 0 ? null : dragOverridesMap;
151
157
  const { params, effectKey } = mergeOverrides({
152
158
  descriptor,
@@ -0,0 +1,5 @@
1
+ import type { CanUpdateSequencePropSource, CanUpdateSequencePropStatus, SourceNumericValue } from './use-schema.js';
2
+ import type { VideoConfigValues } from './video-config.js';
3
+ export declare const evaluateSourceNumericValue: (expression: SourceNumericValue, config: VideoConfigValues | null) => number;
4
+ /** Resolve at the consumer, never in the shared source subscription cache. */
5
+ export declare const evaluateSourcePropStatuses: (props: Record<string, CanUpdateSequencePropSource>, config: VideoConfigValues | null) => Record<string, CanUpdateSequencePropStatus>;