remotion 4.0.507 → 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.
@@ -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
  };
@@ -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';
@@ -1273,4 +1273,4 @@ export declare const Internals: {
1273
1273
  readonly componentName: string;
1274
1274
  }) => import("react").CSSProperties | null;
1275
1275
  };
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, 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, };
@@ -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) => {
@@ -4,7 +4,7 @@ export type OverrideToNodePathGetters = {
4
4
  overrideIdToNodePathMappings: OverrideIdToNodePaths;
5
5
  };
6
6
  export type OverrideToNodeSetters = {
7
- setOverrideIdToNodePath: (overrideId: string, nodePath: SequencePropsSubscriptionKey) => void;
7
+ setOverrideIdToNodePath: (overrideId: string, nodePath: SequencePropsSubscriptionKey | null) => void;
8
8
  };
9
9
  export declare const OverrideIdsToNodePathsGettersContext: import("react").Context<OverrideToNodePathGetters>;
10
10
  export declare const OverrideIdsToNodePathsSettersContext: import("react").Context<OverrideToNodeSetters>;
@@ -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.507";
6
+ export declare const VERSION = "4.0.508";
@@ -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.507';
10
+ exports.VERSION = '4.0.508';
@@ -1340,7 +1340,7 @@ var getSingleChildComponent = (children) => {
1340
1340
  };
1341
1341
 
1342
1342
  // src/version.ts
1343
- var VERSION = "4.0.507";
1343
+ var VERSION = "4.0.508";
1344
1344
 
1345
1345
  // src/multiple-versions-warning.ts
1346
1346
  var checkMultipleRemotionVersions = () => {
@@ -2243,6 +2243,9 @@ var VisualModeSettersContext = React12.createContext({
2243
2243
  },
2244
2244
  setPropStatuses: () => {
2245
2245
  throw new Error("VisualModeSettersContext not initialized");
2246
+ },
2247
+ remapPropStatuses: () => {
2248
+ throw new Error("VisualModeSettersContext not initialized");
2246
2249
  }
2247
2250
  });
2248
2251
  var effectDragOverridesKey = (nodePath, effectIndex) => `${makeSequencePropsSubscriptionKey(nodePath)}.effects.${effectIndex}`;
@@ -2311,6 +2314,20 @@ var SequenceManagerProvider = ({ children }) => {
2311
2314
  return { ...prev, [key]: newKey };
2312
2315
  });
2313
2316
  }, []);
2317
+ const remapPropStatuses = useCallback5((remappings) => {
2318
+ setPropStatusesMapState((prev) => {
2319
+ const next = { ...prev };
2320
+ for (const remapping of remappings) {
2321
+ delete next[makeSequencePropsSubscriptionKey(remapping.previousNodePath)];
2322
+ }
2323
+ for (const remapping of remappings) {
2324
+ if (remapping.nodePath !== null && remapping.result !== null) {
2325
+ next[makeSequencePropsSubscriptionKey(remapping.nodePath)] = remapping.result;
2326
+ }
2327
+ }
2328
+ return next;
2329
+ });
2330
+ }, []);
2314
2331
  const registerSequence = useCallback5((seq) => {
2315
2332
  setSequences((seqs) => {
2316
2333
  return [...seqs, seq];
@@ -2349,14 +2366,16 @@ var SequenceManagerProvider = ({ children }) => {
2349
2366
  clearDragOverrides,
2350
2367
  setEffectDragOverrides,
2351
2368
  clearEffectDragOverrides,
2352
- setPropStatuses
2369
+ setPropStatuses,
2370
+ remapPropStatuses
2353
2371
  };
2354
2372
  }, [
2355
2373
  setDragOverrides,
2356
2374
  clearDragOverrides,
2357
2375
  setEffectDragOverrides,
2358
2376
  clearEffectDragOverrides,
2359
- setPropStatuses
2377
+ setPropStatuses,
2378
+ remapPropStatuses
2360
2379
  ]);
2361
2380
  return /* @__PURE__ */ jsx10(SequenceManagerRefContext.Provider, {
2362
2381
  value: sequencesRef,
@@ -2816,9 +2835,45 @@ var parseTransformOriginValue = (output, parts) => {
2816
2835
  });
2817
2836
  return {
2818
2837
  kind: "translate",
2819
- values: [x.value, y.value, z.value],
2820
- units: [x.unit, y.unit, z.unit],
2821
- dimensions: parts[2] === undefined ? 2 : 3
2838
+ values: [x.value, y.value, z.value, 0],
2839
+ units: [x.unit, y.unit, z.unit, null],
2840
+ dimensions: parts[2] === undefined ? 2 : 3,
2841
+ axisRotation: false
2842
+ };
2843
+ };
2844
+ var parseAxisRotationValue = (output) => {
2845
+ const parts = output.trim().split(/\s+/);
2846
+ const keywordAxis = parts.length === 2 ? parts[0].toLowerCase() : null;
2847
+ if (keywordAxis === "x" || keywordAxis === "y" || keywordAxis === "z") {
2848
+ const keywordAngle = parseStringInterpolationComponent(parts[1], output);
2849
+ if (keywordAngle.kind !== "rotate") {
2850
+ return null;
2851
+ }
2852
+ return {
2853
+ kind: "rotate",
2854
+ values: keywordAxis === "x" ? [1, 0, 0, keywordAngle.value] : keywordAxis === "y" ? [0, 1, 0, keywordAngle.value] : [0, 0, 1, keywordAngle.value],
2855
+ units: [null, null, null, keywordAngle.unit],
2856
+ dimensions: 4,
2857
+ axisRotation: true
2858
+ };
2859
+ }
2860
+ if (parts.length !== 4) {
2861
+ return null;
2862
+ }
2863
+ const axis = parts.slice(0, 3).map(Number);
2864
+ if (!axis.every(Number.isFinite)) {
2865
+ return null;
2866
+ }
2867
+ const vectorAngle = parseStringInterpolationComponent(parts[3], output);
2868
+ if (vectorAngle.kind !== "rotate") {
2869
+ return null;
2870
+ }
2871
+ return {
2872
+ kind: "rotate",
2873
+ values: [axis[0], axis[1], axis[2], vectorAngle.value],
2874
+ units: [null, null, null, vectorAngle.unit],
2875
+ dimensions: 4,
2876
+ axisRotation: true
2822
2877
  };
2823
2878
  };
2824
2879
  var parseStringInterpolationValue = (output) => {
@@ -2828,11 +2883,16 @@ var parseStringInterpolationValue = (output) => {
2828
2883
  }
2829
2884
  return {
2830
2885
  kind: "scale",
2831
- values: [output, output, 1],
2832
- units: [null, null, null],
2833
- dimensions: 1
2886
+ values: [output, output, 1, 0],
2887
+ units: [null, null, null, null],
2888
+ dimensions: 1,
2889
+ axisRotation: false
2834
2890
  };
2835
2891
  }
2892
+ const axisRotation = parseAxisRotationValue(output);
2893
+ if (axisRotation !== null) {
2894
+ return axisRotation;
2895
+ }
2836
2896
  const parts = output.trim().split(/\s+/);
2837
2897
  if (parts.length < 1 || parts.length > 3 || parts[0] === "") {
2838
2898
  throw new TypeError(`String outputRange values must contain 1 to 3 components, but got "${output}"`);
@@ -2853,24 +2913,35 @@ var parseStringInterpolationValue = (output) => {
2853
2913
  const z = parsed[2]?.value ?? 1;
2854
2914
  return {
2855
2915
  kind,
2856
- values: [x, y, z],
2857
- units: [null, null, null],
2858
- dimensions: parsed.length
2916
+ values: [x, y, z, 0],
2917
+ units: [null, null, null, null],
2918
+ dimensions: parsed.length,
2919
+ axisRotation: false
2859
2920
  };
2860
2921
  }
2861
2922
  return {
2862
2923
  kind,
2863
- values: [parsed[0].value, parsed[1]?.value ?? 0, parsed[2]?.value ?? 0],
2864
- units: [parsed[0].unit, parsed[1]?.unit ?? null, parsed[2]?.unit ?? null],
2865
- dimensions: parsed.length
2924
+ values: [parsed[0].value, parsed[1]?.value ?? 0, parsed[2]?.value ?? 0, 0],
2925
+ units: [
2926
+ parsed[0].unit,
2927
+ parsed[1]?.unit ?? null,
2928
+ parsed[2]?.unit ?? null,
2929
+ null
2930
+ ],
2931
+ dimensions: parsed.length,
2932
+ axisRotation: false
2866
2933
  };
2867
2934
  };
2868
2935
  var serializeStringInterpolationValue = ({
2869
2936
  kind,
2870
2937
  values,
2871
2938
  units,
2872
- dimensions
2939
+ dimensions,
2940
+ axisRotation
2873
2941
  }) => {
2942
+ if (axisRotation) {
2943
+ return `${stringifyNumber(values[0])} ${stringifyNumber(values[1])} ${stringifyNumber(values[2])} ${stringifyNumber(values[3])}${units[3]}`;
2944
+ }
2874
2945
  if (kind === "scale") {
2875
2946
  return values.slice(0, dimensions).map((value) => stringifyNumber(value)).join(" ");
2876
2947
  }
@@ -3038,7 +3109,26 @@ var interpolateString = ({
3038
3109
  outputRange,
3039
3110
  options
3040
3111
  }) => {
3041
- const parsedOutputRange = outputRange.map(parseStringInterpolationValue);
3112
+ const initiallyParsedOutputRange = outputRange.map(parseStringInterpolationValue);
3113
+ const hasAxisRotation = initiallyParsedOutputRange.some((parsed) => parsed.axisRotation);
3114
+ const parsedOutputRange = hasAxisRotation ? initiallyParsedOutputRange.map((parsed) => {
3115
+ if (parsed.kind !== "rotate") {
3116
+ return parsed;
3117
+ }
3118
+ if (parsed.axisRotation) {
3119
+ return parsed;
3120
+ }
3121
+ if (parsed.dimensions !== 1) {
3122
+ throw new TypeError("Cannot interpolate a multi-angle rotate value with an axis rotation");
3123
+ }
3124
+ return {
3125
+ kind: "rotate",
3126
+ values: [0, 0, 1, parsed.values[0]],
3127
+ units: [null, null, null, parsed.units[0]],
3128
+ dimensions: 4,
3129
+ axisRotation: true
3130
+ };
3131
+ }) : initiallyParsedOutputRange;
3042
3132
  const kind = parsedOutputRange[0]?.kind;
3043
3133
  if (kind === undefined) {
3044
3134
  throw new Error("outputRange must have at least 1 element");
@@ -3050,12 +3140,16 @@ var interpolateString = ({
3050
3140
  }
3051
3141
  const dimensions = Math.max(...parsedOutputRange.map((parsed) => parsed.dimensions));
3052
3142
  const units = [
3143
+ null,
3053
3144
  null,
3054
3145
  null,
3055
3146
  null
3056
3147
  ];
3057
3148
  if (kind !== "scale") {
3058
3149
  for (let axis = 0;axis < dimensions; axis++) {
3150
+ if (hasAxisRotation && axis < 3) {
3151
+ continue;
3152
+ }
3059
3153
  for (const parsed of parsedOutputRange) {
3060
3154
  const unit = parsed.units[axis];
3061
3155
  if (unit === null) {
@@ -3074,7 +3168,7 @@ var interpolateString = ({
3074
3168
  }
3075
3169
  }
3076
3170
  }
3077
- const values = [0, 0, 0];
3171
+ const values = [0, 0, 0, 0];
3078
3172
  for (let axis = 0;axis < dimensions; axis++) {
3079
3173
  values[axis] = interpolateNumber({
3080
3174
  input,
@@ -3087,7 +3181,8 @@ var interpolateString = ({
3087
3181
  kind,
3088
3182
  values,
3089
3183
  units,
3090
- dimensions
3184
+ dimensions,
3185
+ axisRotation: hasAxisRotation
3091
3186
  });
3092
3187
  };
3093
3188
  var validateTupleOutputRange = (outputRange) => {
@@ -191,9 +191,45 @@ var parseTransformOriginValue = (output, parts) => {
191
191
  });
192
192
  return {
193
193
  kind: "translate",
194
- values: [x.value, y.value, z.value],
195
- units: [x.unit, y.unit, z.unit],
196
- dimensions: parts[2] === undefined ? 2 : 3
194
+ values: [x.value, y.value, z.value, 0],
195
+ units: [x.unit, y.unit, z.unit, null],
196
+ dimensions: parts[2] === undefined ? 2 : 3,
197
+ axisRotation: false
198
+ };
199
+ };
200
+ var parseAxisRotationValue = (output) => {
201
+ const parts = output.trim().split(/\s+/);
202
+ const keywordAxis = parts.length === 2 ? parts[0].toLowerCase() : null;
203
+ if (keywordAxis === "x" || keywordAxis === "y" || keywordAxis === "z") {
204
+ const keywordAngle = parseStringInterpolationComponent(parts[1], output);
205
+ if (keywordAngle.kind !== "rotate") {
206
+ return null;
207
+ }
208
+ return {
209
+ kind: "rotate",
210
+ values: keywordAxis === "x" ? [1, 0, 0, keywordAngle.value] : keywordAxis === "y" ? [0, 1, 0, keywordAngle.value] : [0, 0, 1, keywordAngle.value],
211
+ units: [null, null, null, keywordAngle.unit],
212
+ dimensions: 4,
213
+ axisRotation: true
214
+ };
215
+ }
216
+ if (parts.length !== 4) {
217
+ return null;
218
+ }
219
+ const axis = parts.slice(0, 3).map(Number);
220
+ if (!axis.every(Number.isFinite)) {
221
+ return null;
222
+ }
223
+ const vectorAngle = parseStringInterpolationComponent(parts[3], output);
224
+ if (vectorAngle.kind !== "rotate") {
225
+ return null;
226
+ }
227
+ return {
228
+ kind: "rotate",
229
+ values: [axis[0], axis[1], axis[2], vectorAngle.value],
230
+ units: [null, null, null, vectorAngle.unit],
231
+ dimensions: 4,
232
+ axisRotation: true
197
233
  };
198
234
  };
199
235
  var parseStringInterpolationValue = (output) => {
@@ -203,11 +239,16 @@ var parseStringInterpolationValue = (output) => {
203
239
  }
204
240
  return {
205
241
  kind: "scale",
206
- values: [output, output, 1],
207
- units: [null, null, null],
208
- dimensions: 1
242
+ values: [output, output, 1, 0],
243
+ units: [null, null, null, null],
244
+ dimensions: 1,
245
+ axisRotation: false
209
246
  };
210
247
  }
248
+ const axisRotation = parseAxisRotationValue(output);
249
+ if (axisRotation !== null) {
250
+ return axisRotation;
251
+ }
211
252
  const parts = output.trim().split(/\s+/);
212
253
  if (parts.length < 1 || parts.length > 3 || parts[0] === "") {
213
254
  throw new TypeError(`String outputRange values must contain 1 to 3 components, but got "${output}"`);
@@ -228,24 +269,35 @@ var parseStringInterpolationValue = (output) => {
228
269
  const z = parsed[2]?.value ?? 1;
229
270
  return {
230
271
  kind,
231
- values: [x, y, z],
232
- units: [null, null, null],
233
- dimensions: parsed.length
272
+ values: [x, y, z, 0],
273
+ units: [null, null, null, null],
274
+ dimensions: parsed.length,
275
+ axisRotation: false
234
276
  };
235
277
  }
236
278
  return {
237
279
  kind,
238
- values: [parsed[0].value, parsed[1]?.value ?? 0, parsed[2]?.value ?? 0],
239
- units: [parsed[0].unit, parsed[1]?.unit ?? null, parsed[2]?.unit ?? null],
240
- dimensions: parsed.length
280
+ values: [parsed[0].value, parsed[1]?.value ?? 0, parsed[2]?.value ?? 0, 0],
281
+ units: [
282
+ parsed[0].unit,
283
+ parsed[1]?.unit ?? null,
284
+ parsed[2]?.unit ?? null,
285
+ null
286
+ ],
287
+ dimensions: parsed.length,
288
+ axisRotation: false
241
289
  };
242
290
  };
243
291
  var serializeStringInterpolationValue = ({
244
292
  kind,
245
293
  values,
246
294
  units,
247
- dimensions
295
+ dimensions,
296
+ axisRotation
248
297
  }) => {
298
+ if (axisRotation) {
299
+ return `${stringifyNumber(values[0])} ${stringifyNumber(values[1])} ${stringifyNumber(values[2])} ${stringifyNumber(values[3])}${units[3]}`;
300
+ }
249
301
  if (kind === "scale") {
250
302
  return values.slice(0, dimensions).map((value) => stringifyNumber(value)).join(" ");
251
303
  }
@@ -413,7 +465,26 @@ var interpolateString = ({
413
465
  outputRange,
414
466
  options
415
467
  }) => {
416
- const parsedOutputRange = outputRange.map(parseStringInterpolationValue);
468
+ const initiallyParsedOutputRange = outputRange.map(parseStringInterpolationValue);
469
+ const hasAxisRotation = initiallyParsedOutputRange.some((parsed) => parsed.axisRotation);
470
+ const parsedOutputRange = hasAxisRotation ? initiallyParsedOutputRange.map((parsed) => {
471
+ if (parsed.kind !== "rotate") {
472
+ return parsed;
473
+ }
474
+ if (parsed.axisRotation) {
475
+ return parsed;
476
+ }
477
+ if (parsed.dimensions !== 1) {
478
+ throw new TypeError("Cannot interpolate a multi-angle rotate value with an axis rotation");
479
+ }
480
+ return {
481
+ kind: "rotate",
482
+ values: [0, 0, 1, parsed.values[0]],
483
+ units: [null, null, null, parsed.units[0]],
484
+ dimensions: 4,
485
+ axisRotation: true
486
+ };
487
+ }) : initiallyParsedOutputRange;
417
488
  const kind = parsedOutputRange[0]?.kind;
418
489
  if (kind === undefined) {
419
490
  throw new Error("outputRange must have at least 1 element");
@@ -425,12 +496,16 @@ var interpolateString = ({
425
496
  }
426
497
  const dimensions = Math.max(...parsedOutputRange.map((parsed) => parsed.dimensions));
427
498
  const units = [
499
+ null,
428
500
  null,
429
501
  null,
430
502
  null
431
503
  ];
432
504
  if (kind !== "scale") {
433
505
  for (let axis = 0;axis < dimensions; axis++) {
506
+ if (hasAxisRotation && axis < 3) {
507
+ continue;
508
+ }
434
509
  for (const parsed of parsedOutputRange) {
435
510
  const unit = parsed.units[axis];
436
511
  if (unit === null) {
@@ -449,7 +524,7 @@ var interpolateString = ({
449
524
  }
450
525
  }
451
526
  }
452
- const values = [0, 0, 0];
527
+ const values = [0, 0, 0, 0];
453
528
  for (let axis = 0;axis < dimensions; axis++) {
454
529
  values[axis] = interpolateNumber({
455
530
  input,
@@ -462,7 +537,8 @@ var interpolateString = ({
462
537
  kind,
463
538
  values,
464
539
  units,
465
- dimensions
540
+ dimensions,
541
+ axisRotation: hasAxisRotation
466
542
  });
467
543
  };
468
544
  var validateTupleOutputRange = (outputRange) => {
@@ -1,5 +1,5 @@
1
1
  // src/version.ts
2
- var VERSION = "4.0.507";
2
+ var VERSION = "4.0.508";
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.507",
6
+ "version": "4.0.508",
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.4.3",
38
- "@remotion/eslint-config-internal": "4.0.507",
38
+ "@remotion/eslint-config-internal": "4.0.508",
39
39
  "eslint": "9.19.0",
40
40
  "@typescript/native-preview": "7.0.0-dev.20260217.1"
41
41
  },