remotion 4.0.526 → 4.0.527

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.
@@ -5,7 +5,7 @@ import type { AnyCompMetadata, AnyComposition, AudioOrVideoAsset, JsxComponentId
5
5
  import type { DelayRenderScope } from './delay-render.js';
6
6
  import { type TFolder } from './Folder.js';
7
7
  import type { StaticFile } from './get-static-files.js';
8
- import type { AssetFieldSchema, ArrayFieldSchema, ArrayItemFieldSchema, CaptionsFieldSchema, InteractivitySchemaField, InteractivitySchema } from './interactivity-schema.js';
8
+ import type { ArrayFieldSchema, ArrayItemFieldSchema, AssetFieldSchema, CaptionsFieldSchema, InteractivitySchema, InteractivitySchemaField } from './interactivity-schema.js';
9
9
  import type { LogLevel } from './log.js';
10
10
  import type { ProResProfile } from './prores-profile.js';
11
11
  import type { PixelFormat, VideoImageFormat } from './render-types.js';
@@ -135,7 +135,7 @@ export * from './internals.js';
135
135
  export { interpolateColors, type InterpolateColorsOptions, } from './interpolate-colors.js';
136
136
  export { LogLevel } from './log.js';
137
137
  export { Loop } from './loop/index.js';
138
- export { assertValidInterpolateEasingOption, assertValidInterpolatePosterizeOption, EasingFunction, ExtrapolateType, interpolate, InterpolateOutputOption, InterpolateOptions, random, RandomSeed, } from './no-react';
138
+ export { assertValidInterpolateEasingOption, assertValidInterpolatePosterizeOption, EasingFunction, ExtrapolateType, interpolate, InterpolateOptions, InterpolateOutputOption, InterpolateOutputType, random, RandomSeed, } from './no-react';
139
139
  export { prefetch, PrefetchOnProgress } from './prefetch.js';
140
140
  export { registerRoot } from './register-root.js';
141
141
  export type { PixelFormat, VideoImageFormat } from './render-types.js';
@@ -184,4 +184,4 @@ export type _InternalTypes = {
184
184
  TRenderAsset: TRenderAsset;
185
185
  ProResProfile: ProResProfile;
186
186
  };
187
- export type { AnyComposition, AssetFieldSchema, ArrayFieldSchema, ArrayItemFieldSchema, CaptionsFieldSchema, DelayRenderScope, JsxComponentIdentity, LoopDisplay, RuntimeValueSnapshot, RuntimeValueStore, SequenceControls, SequenceRegistrationControls, InteractivitySchemaField, InteractivitySchema, UseBufferState, };
187
+ export type { AnyComposition, ArrayFieldSchema, ArrayItemFieldSchema, AssetFieldSchema, CaptionsFieldSchema, DelayRenderScope, InteractivitySchema, InteractivitySchemaField, JsxComponentIdentity, LoopDisplay, RuntimeValueSnapshot, RuntimeValueStore, SequenceControls, SequenceRegistrationControls, UseBufferState, };
@@ -1,5 +1,6 @@
1
1
  export type ExtrapolateType = 'extend' | 'identity' | 'clamp' | 'wrap';
2
2
  export type InterpolateOutputOption = 'linear' | 'perceptual-scale';
3
+ export type InterpolateOutputType = 'font-weight' | 'scale' | 'translate' | 'rotate' | 'transform-origin';
3
4
  /**
4
5
  * @description This function allows you to map a range of values to another with a concise syntax
5
6
  * @see [Documentation](https://www.remotion.dev/docs/interpolate)
@@ -12,6 +13,7 @@ export type InterpolateOptions = Partial<{
12
13
  extrapolateLeft: ExtrapolateType;
13
14
  extrapolateRight: ExtrapolateType;
14
15
  output: InterpolateOutputOption;
16
+ outputType: InterpolateOutputType;
15
17
  posterize: number;
16
18
  }>;
17
19
  type NumericTuple = readonly [number, ...number[]];
@@ -21,6 +23,9 @@ type WidenNumericTuple<T extends readonly number[]> = {
21
23
  export declare function assertValidInterpolateEasingOption(easing: EasingFunction | readonly EasingFunction[] | undefined, inputRangeLength: number): void;
22
24
  export declare function assertValidInterpolatePosterizeOption(posterize: number | undefined): void;
23
25
  export declare function interpolate(input: number, inputRange: readonly number[], outputRange: readonly number[], options?: InterpolateOptions): number;
26
+ export declare function interpolate(input: number, inputRange: readonly number[], outputRange: readonly (number | string)[], options: InterpolateOptions & {
27
+ outputType: 'font-weight';
28
+ }): number;
24
29
  export declare function interpolate(input: number, inputRange: readonly number[], outputRange: readonly string[], options?: InterpolateOptions): string;
25
30
  export declare function interpolate<const Tuple extends NumericTuple>(input: number, inputRange: readonly number[], outputRange: readonly Tuple[], options?: InterpolateOptions): WidenNumericTuple<Tuple>;
26
31
  export declare function interpolate(input: number, inputRange: readonly number[], outputRange: readonly (readonly number[])[], options?: InterpolateOptions): number[];
@@ -254,7 +254,7 @@ const parseAxisRotationValue = (output) => {
254
254
  axisRotation: true,
255
255
  };
256
256
  };
257
- const parseStringInterpolationValue = (output) => {
257
+ const parseStringInterpolationValue = (output, outputType) => {
258
258
  var _a, _b, _c, _d, _e, _f;
259
259
  var _g, _h, _j, _k, _l, _m;
260
260
  if (typeof output === 'number') {
@@ -269,8 +269,20 @@ const parseStringInterpolationValue = (output) => {
269
269
  axisRotation: false,
270
270
  };
271
271
  }
272
+ if (outputType === 'transform-origin') {
273
+ const transformOriginParts = output.trim().split(/\s+/);
274
+ if (transformOriginParts.length < 1 ||
275
+ transformOriginParts.length > 3 ||
276
+ transformOriginParts[0] === '') {
277
+ throw new TypeError(`String outputRange values must contain 1 to 3 components, but got "${output}"`);
278
+ }
279
+ return parseTransformOriginValue(output, transformOriginParts);
280
+ }
272
281
  const axisRotation = parseAxisRotationValue(output);
273
282
  if (axisRotation !== null) {
283
+ if (outputType !== undefined && outputType !== 'rotate') {
284
+ throw new TypeError(`Cannot interpolate "${output}" as ${outputType} because it is a rotate value`);
285
+ }
274
286
  return axisRotation;
275
287
  }
276
288
  const parts = output.trim().split(/\s+/);
@@ -278,6 +290,9 @@ const parseStringInterpolationValue = (output) => {
278
290
  throw new TypeError(`String outputRange values must contain 1 to 3 components, but got "${output}"`);
279
291
  }
280
292
  if (parts.some((part) => transformOriginKeywords.has(part.toLowerCase()))) {
293
+ if (outputType !== undefined) {
294
+ throw new TypeError(`Cannot interpolate "${output}" as ${outputType} because it is a transform-origin value`);
295
+ }
281
296
  return parseTransformOriginValue(output, parts);
282
297
  }
283
298
  const parsed = parts.map((part) => parseStringInterpolationComponent(part, output));
@@ -287,6 +302,9 @@ const parseStringInterpolationValue = (output) => {
287
302
  throw new TypeError(`Cannot interpolate "${output}" because it mixes ${kind} and ${part.kind} values`);
288
303
  }
289
304
  }
305
+ if (outputType !== undefined && outputType !== kind) {
306
+ throw new TypeError(`Cannot interpolate "${output}" as ${outputType} because it is a ${kind} value`);
307
+ }
290
308
  if (kind === 'scale') {
291
309
  const x = parsed[0].value;
292
310
  const y = (_g = (_a = parsed[1]) === null || _a === void 0 ? void 0 : _a.value) !== null && _g !== void 0 ? _g : x;
@@ -486,9 +504,9 @@ const interpolateNumber = ({ input, inputRange, outputRange, options, }) => {
486
504
  }
487
505
  return result;
488
506
  };
489
- const interpolateString = ({ input, inputRange, outputRange, options, }) => {
507
+ const interpolateString = ({ input, inputRange, outputRange, options, outputType, }) => {
490
508
  var _a;
491
- const initiallyParsedOutputRange = outputRange.map(parseStringInterpolationValue);
509
+ const initiallyParsedOutputRange = outputRange.map((output) => parseStringInterpolationValue(output, outputType));
492
510
  const hasAxisRotation = initiallyParsedOutputRange.some((parsed) => parsed.axisRotation);
493
511
  const posterizedInput = (options === null || options === void 0 ? void 0 : options.posterize) === undefined
494
512
  ? input
@@ -589,6 +607,35 @@ const interpolateString = ({ input, inputRange, outputRange, options, }) => {
589
607
  axisRotation: hasAxisRotation,
590
608
  });
591
609
  };
610
+ const interpolateFontWeight = ({ input, inputRange, outputRange, options, }) => {
611
+ const normalizedOutputRange = outputRange.map((output) => {
612
+ if (typeof output === 'string') {
613
+ const lowerCaseOutput = output.toLowerCase();
614
+ if (lowerCaseOutput === 'normal') {
615
+ return 400;
616
+ }
617
+ if (lowerCaseOutput === 'bold') {
618
+ return 700;
619
+ }
620
+ }
621
+ const match = typeof output === 'string' ? cssNumberRegex.exec(output) : null;
622
+ const value = typeof output === 'number'
623
+ ? output
624
+ : match !== null && match[2] === undefined
625
+ ? Number(match[1])
626
+ : Number.NaN;
627
+ if (!Number.isFinite(value) || value < 1 || value > 1000) {
628
+ throw new TypeError(`Cannot interpolate font weight "${output}". Expected "normal", "bold", or a number between 1 and 1000`);
629
+ }
630
+ return value;
631
+ });
632
+ return interpolateNumber({
633
+ input,
634
+ inputRange,
635
+ outputRange: normalizedOutputRange,
636
+ options,
637
+ });
638
+ };
592
639
  const interpolateDiscreteString = ({ input, inputRange, outputRange, options, }) => {
593
640
  if (inputRange.length === 1) {
594
641
  return outputRange[0];
@@ -725,6 +772,17 @@ function assertValidInterpolateOutputOption(output) {
725
772
  }
726
773
  throw new Error(`output must be "linear" or "perceptual-scale", but got ${String(output)}`);
727
774
  }
775
+ function assertValidInterpolateOutputType(outputType) {
776
+ if (outputType === undefined ||
777
+ outputType === 'font-weight' ||
778
+ outputType === 'scale' ||
779
+ outputType === 'translate' ||
780
+ outputType === 'rotate' ||
781
+ outputType === 'transform-origin') {
782
+ return;
783
+ }
784
+ throw new Error(`outputType must be "font-weight", "scale", "translate", "rotate", or "transform-origin", but got ${String(outputType)}`);
785
+ }
728
786
  function interpolate(input, inputRange, outputRange, options) {
729
787
  if (typeof input === 'undefined') {
730
788
  throw new Error('input can not be undefined');
@@ -747,19 +805,41 @@ function interpolate(input, inputRange, outputRange, options) {
747
805
  assertValidInterpolateEasingOption(options === null || options === void 0 ? void 0 : options.easing, inputRange.length);
748
806
  assertValidInterpolatePosterizeOption(options === null || options === void 0 ? void 0 : options.posterize);
749
807
  assertValidInterpolateOutputOption(options === null || options === void 0 ? void 0 : options.output);
808
+ assertValidInterpolateOutputType(options === null || options === void 0 ? void 0 : options.outputType);
750
809
  if (typeof input !== 'number') {
751
810
  throw new TypeError('Cannot interpolate an input which is not a number');
752
811
  }
753
812
  if (!Array.isArray(outputRange)) {
754
813
  throw new Error('outputRange must contain only numbers');
755
814
  }
815
+ const outputType = options === null || options === void 0 ? void 0 : options.outputType;
816
+ if (outputType === 'font-weight') {
817
+ if (!outputRange.every((output) => typeof output === 'number' || typeof output === 'string')) {
818
+ throw new TypeError('Font weight outputRange must contain only numbers or strings');
819
+ }
820
+ return interpolateFontWeight({
821
+ input,
822
+ inputRange,
823
+ outputRange,
824
+ options,
825
+ });
826
+ }
756
827
  const hasStringOutput = outputRange.some((output) => typeof output === 'string');
828
+ if (outputType !== undefined && outputType !== 'scale' && !hasStringOutput) {
829
+ throw new TypeError(`${outputType} outputRange must contain strings with the appropriate CSS units`);
830
+ }
757
831
  if (hasStringOutput) {
758
832
  if (!outputRange.every((output) => typeof output === 'string' || typeof output === 'number')) {
759
833
  throw new TypeError('outputRange must contain only numbers, or supported scale, translate, and rotate strings');
760
834
  }
761
835
  try {
762
- return interpolateString({ input, inputRange, outputRange, options });
836
+ return interpolateString({
837
+ input,
838
+ inputRange,
839
+ outputRange,
840
+ options,
841
+ outputType,
842
+ });
763
843
  }
764
844
  catch (error) {
765
845
  if (!outputRange.every((output) => typeof output === 'string')) {
@@ -767,7 +847,7 @@ function interpolate(input, inputRange, outputRange, options) {
767
847
  }
768
848
  const hasNonNumericString = outputRange.some((output) => {
769
849
  try {
770
- parseStringInterpolationValue(output);
850
+ parseStringInterpolationValue(output, outputType);
771
851
  return false;
772
852
  }
773
853
  catch (parseError) {
@@ -1,7 +1,7 @@
1
1
  export type { ArtifactAsset, AudioOrVideoAsset, InlineAudioAsset, TRenderAsset, } from './CompositionManager';
2
2
  export type { DownloadBehavior } from './download-behavior';
3
3
  export { assertValidInterpolateEasingOption, assertValidInterpolatePosterizeOption, interpolate, } from './interpolate';
4
- export type { EasingFunction, ExtrapolateType, InterpolateOutputOption, InterpolateOptions, } from './interpolate';
4
+ export type { EasingFunction, ExtrapolateType, InterpolateOptions, InterpolateOutputOption, InterpolateOutputType, } from './interpolate';
5
5
  export { random } from './random.js';
6
6
  export type { RandomSeed } from './random.js';
7
7
  export type { VideoConfig } from './video-config';
@@ -64,15 +64,24 @@ function advance({ animation, now, config, }) {
64
64
  }
65
65
  const calculationCache = {};
66
66
  function springCalculation({ frame, fps, config = {}, }) {
67
+ var _a, _b, _c, _d;
67
68
  const from = 0;
68
69
  const to = 1;
70
+ // An explicit `undefined` (e.g. a forwarded optional prop) must not
71
+ // override the defaults, otherwise the physics turn into NaN
72
+ const resolvedConfig = {
73
+ damping: (_a = config.damping) !== null && _a !== void 0 ? _a : defaultSpringConfig.damping,
74
+ mass: (_b = config.mass) !== null && _b !== void 0 ? _b : defaultSpringConfig.mass,
75
+ stiffness: (_c = config.stiffness) !== null && _c !== void 0 ? _c : defaultSpringConfig.stiffness,
76
+ overshootClamping: (_d = config.overshootClamping) !== null && _d !== void 0 ? _d : defaultSpringConfig.overshootClamping,
77
+ };
69
78
  const cacheKey = [
70
79
  frame,
71
80
  fps,
72
- config.damping,
73
- config.mass,
74
- config.overshootClamping,
75
- config.stiffness,
81
+ resolvedConfig.damping,
82
+ resolvedConfig.mass,
83
+ resolvedConfig.overshootClamping,
84
+ resolvedConfig.stiffness,
76
85
  ].join('-');
77
86
  if (calculationCache[cacheKey]) {
78
87
  return calculationCache[cacheKey];
@@ -91,20 +100,14 @@ function springCalculation({ frame, fps, config = {}, }) {
91
100
  animation = advance({
92
101
  animation,
93
102
  now: time,
94
- config: {
95
- ...defaultSpringConfig,
96
- ...config,
97
- },
103
+ config: resolvedConfig,
98
104
  });
99
105
  }
100
106
  if (unevenRest > 0) {
101
107
  animation = advance({
102
108
  animation,
103
109
  now: (frameClamped / fps) * 1000,
104
- config: {
105
- ...defaultSpringConfig,
106
- ...config,
107
- },
110
+ config: resolvedConfig,
108
111
  });
109
112
  }
110
113
  calculationCache[cacheKey] = animation;
@@ -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.526";
6
+ export declare const VERSION = "4.0.527";
@@ -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.526';
10
+ exports.VERSION = '4.0.527';
@@ -1537,7 +1537,7 @@ var Composition = (props) => {
1537
1537
  };
1538
1538
 
1539
1539
  // src/version.ts
1540
- var VERSION = "4.0.526";
1540
+ var VERSION = "4.0.527";
1541
1541
 
1542
1542
  // src/multiple-versions-warning.ts
1543
1543
  var checkMultipleRemotionVersions = () => {
@@ -3226,7 +3226,7 @@ var parseAxisRotationValue = (output) => {
3226
3226
  axisRotation: true
3227
3227
  };
3228
3228
  };
3229
- var parseStringInterpolationValue = (output) => {
3229
+ var parseStringInterpolationValue = (output, outputType) => {
3230
3230
  if (typeof output === "number") {
3231
3231
  if (!Number.isFinite(output)) {
3232
3232
  throw new Error(`outputRange must contain only finite numbers, but got [${output}]`);
@@ -3239,8 +3239,18 @@ var parseStringInterpolationValue = (output) => {
3239
3239
  axisRotation: false
3240
3240
  };
3241
3241
  }
3242
+ if (outputType === "transform-origin") {
3243
+ const transformOriginParts = output.trim().split(/\s+/);
3244
+ if (transformOriginParts.length < 1 || transformOriginParts.length > 3 || transformOriginParts[0] === "") {
3245
+ throw new TypeError(`String outputRange values must contain 1 to 3 components, but got "${output}"`);
3246
+ }
3247
+ return parseTransformOriginValue(output, transformOriginParts);
3248
+ }
3242
3249
  const axisRotation = parseAxisRotationValue(output);
3243
3250
  if (axisRotation !== null) {
3251
+ if (outputType !== undefined && outputType !== "rotate") {
3252
+ throw new TypeError(`Cannot interpolate "${output}" as ${outputType} because it is a rotate value`);
3253
+ }
3244
3254
  return axisRotation;
3245
3255
  }
3246
3256
  const parts = output.trim().split(/\s+/);
@@ -3248,6 +3258,9 @@ var parseStringInterpolationValue = (output) => {
3248
3258
  throw new TypeError(`String outputRange values must contain 1 to 3 components, but got "${output}"`);
3249
3259
  }
3250
3260
  if (parts.some((part) => transformOriginKeywords.has(part.toLowerCase()))) {
3261
+ if (outputType !== undefined) {
3262
+ throw new TypeError(`Cannot interpolate "${output}" as ${outputType} because it is a transform-origin value`);
3263
+ }
3251
3264
  return parseTransformOriginValue(output, parts);
3252
3265
  }
3253
3266
  const parsed = parts.map((part) => parseStringInterpolationComponent(part, output));
@@ -3257,6 +3270,9 @@ var parseStringInterpolationValue = (output) => {
3257
3270
  throw new TypeError(`Cannot interpolate "${output}" because it mixes ${kind} and ${part.kind} values`);
3258
3271
  }
3259
3272
  }
3273
+ if (outputType !== undefined && outputType !== kind) {
3274
+ throw new TypeError(`Cannot interpolate "${output}" as ${outputType} because it is a ${kind} value`);
3275
+ }
3260
3276
  if (kind === "scale") {
3261
3277
  const x = parsed[0].value;
3262
3278
  const y = parsed[1]?.value ?? x;
@@ -3457,9 +3473,10 @@ var interpolateString = ({
3457
3473
  input,
3458
3474
  inputRange,
3459
3475
  outputRange,
3460
- options
3476
+ options,
3477
+ outputType
3461
3478
  }) => {
3462
- const initiallyParsedOutputRange = outputRange.map(parseStringInterpolationValue);
3479
+ const initiallyParsedOutputRange = outputRange.map((output) => parseStringInterpolationValue(output, outputType));
3463
3480
  const hasAxisRotation = initiallyParsedOutputRange.some((parsed) => parsed.axisRotation);
3464
3481
  const posterizedInput = options?.posterize === undefined ? input : Math.floor(input / options.posterize) * options.posterize;
3465
3482
  const segmentIndex = inputRange.length === 1 ? 0 : findRange(posterizedInput, inputRange);
@@ -3539,6 +3556,36 @@ var interpolateString = ({
3539
3556
  axisRotation: hasAxisRotation
3540
3557
  });
3541
3558
  };
3559
+ var interpolateFontWeight = ({
3560
+ input,
3561
+ inputRange,
3562
+ outputRange,
3563
+ options
3564
+ }) => {
3565
+ const normalizedOutputRange = outputRange.map((output) => {
3566
+ if (typeof output === "string") {
3567
+ const lowerCaseOutput = output.toLowerCase();
3568
+ if (lowerCaseOutput === "normal") {
3569
+ return 400;
3570
+ }
3571
+ if (lowerCaseOutput === "bold") {
3572
+ return 700;
3573
+ }
3574
+ }
3575
+ const match = typeof output === "string" ? cssNumberRegex.exec(output) : null;
3576
+ const value = typeof output === "number" ? output : match !== null && match[2] === undefined ? Number(match[1]) : Number.NaN;
3577
+ if (!Number.isFinite(value) || value < 1 || value > 1000) {
3578
+ throw new TypeError(`Cannot interpolate font weight "${output}". Expected "normal", "bold", or a number between 1 and 1000`);
3579
+ }
3580
+ return value;
3581
+ });
3582
+ return interpolateNumber({
3583
+ input,
3584
+ inputRange,
3585
+ outputRange: normalizedOutputRange,
3586
+ options
3587
+ });
3588
+ };
3542
3589
  var interpolateDiscreteString = ({
3543
3590
  input,
3544
3591
  inputRange,
@@ -3670,6 +3717,12 @@ function assertValidInterpolateOutputOption(output) {
3670
3717
  }
3671
3718
  throw new Error(`output must be "linear" or "perceptual-scale", but got ${String(output)}`);
3672
3719
  }
3720
+ function assertValidInterpolateOutputType(outputType) {
3721
+ if (outputType === undefined || outputType === "font-weight" || outputType === "scale" || outputType === "translate" || outputType === "rotate" || outputType === "transform-origin") {
3722
+ return;
3723
+ }
3724
+ throw new Error(`outputType must be "font-weight", "scale", "translate", "rotate", or "transform-origin", but got ${String(outputType)}`);
3725
+ }
3673
3726
  function interpolate(input, inputRange, outputRange, options) {
3674
3727
  if (typeof input === "undefined") {
3675
3728
  throw new Error("input can not be undefined");
@@ -3688,26 +3741,48 @@ function interpolate(input, inputRange, outputRange, options) {
3688
3741
  assertValidInterpolateEasingOption(options?.easing, inputRange.length);
3689
3742
  assertValidInterpolatePosterizeOption(options?.posterize);
3690
3743
  assertValidInterpolateOutputOption(options?.output);
3744
+ assertValidInterpolateOutputType(options?.outputType);
3691
3745
  if (typeof input !== "number") {
3692
3746
  throw new TypeError("Cannot interpolate an input which is not a number");
3693
3747
  }
3694
3748
  if (!Array.isArray(outputRange)) {
3695
3749
  throw new Error("outputRange must contain only numbers");
3696
3750
  }
3751
+ const outputType = options?.outputType;
3752
+ if (outputType === "font-weight") {
3753
+ if (!outputRange.every((output) => typeof output === "number" || typeof output === "string")) {
3754
+ throw new TypeError("Font weight outputRange must contain only numbers or strings");
3755
+ }
3756
+ return interpolateFontWeight({
3757
+ input,
3758
+ inputRange,
3759
+ outputRange,
3760
+ options
3761
+ });
3762
+ }
3697
3763
  const hasStringOutput = outputRange.some((output) => typeof output === "string");
3764
+ if (outputType !== undefined && outputType !== "scale" && !hasStringOutput) {
3765
+ throw new TypeError(`${outputType} outputRange must contain strings with the appropriate CSS units`);
3766
+ }
3698
3767
  if (hasStringOutput) {
3699
3768
  if (!outputRange.every((output) => typeof output === "string" || typeof output === "number")) {
3700
3769
  throw new TypeError("outputRange must contain only numbers, or supported scale, translate, and rotate strings");
3701
3770
  }
3702
3771
  try {
3703
- return interpolateString({ input, inputRange, outputRange, options });
3772
+ return interpolateString({
3773
+ input,
3774
+ inputRange,
3775
+ outputRange,
3776
+ options,
3777
+ outputType
3778
+ });
3704
3779
  } catch (error2) {
3705
3780
  if (!outputRange.every((output) => typeof output === "string")) {
3706
3781
  throw error2;
3707
3782
  }
3708
3783
  const hasNonNumericString = outputRange.some((output) => {
3709
3784
  try {
3710
- parseStringInterpolationValue(output);
3785
+ parseStringInterpolationValue(output, outputType);
3711
3786
  return false;
3712
3787
  } catch (parseError) {
3713
3788
  return parseError instanceof UnsupportedStringInterpolationValueError;
@@ -3846,13 +3921,19 @@ function springCalculation({
3846
3921
  }) {
3847
3922
  const from = 0;
3848
3923
  const to = 1;
3924
+ const resolvedConfig = {
3925
+ damping: config.damping ?? defaultSpringConfig.damping,
3926
+ mass: config.mass ?? defaultSpringConfig.mass,
3927
+ stiffness: config.stiffness ?? defaultSpringConfig.stiffness,
3928
+ overshootClamping: config.overshootClamping ?? defaultSpringConfig.overshootClamping
3929
+ };
3849
3930
  const cacheKey = [
3850
3931
  frame,
3851
3932
  fps,
3852
- config.damping,
3853
- config.mass,
3854
- config.overshootClamping,
3855
- config.stiffness
3933
+ resolvedConfig.damping,
3934
+ resolvedConfig.mass,
3935
+ resolvedConfig.overshootClamping,
3936
+ resolvedConfig.stiffness
3856
3937
  ].join("-");
3857
3938
  if (calculationCache[cacheKey]) {
3858
3939
  return calculationCache[cacheKey];
@@ -3871,20 +3952,14 @@ function springCalculation({
3871
3952
  animation = advance({
3872
3953
  animation,
3873
3954
  now: time,
3874
- config: {
3875
- ...defaultSpringConfig,
3876
- ...config
3877
- }
3955
+ config: resolvedConfig
3878
3956
  });
3879
3957
  }
3880
3958
  if (unevenRest > 0) {
3881
3959
  animation = advance({
3882
3960
  animation,
3883
3961
  now: frameClamped / fps * 1000,
3884
- config: {
3885
- ...defaultSpringConfig,
3886
- ...config
3887
- }
3962
+ config: resolvedConfig
3888
3963
  });
3889
3964
  }
3890
3965
  calculationCache[cacheKey] = animation;
@@ -237,13 +237,19 @@ function springCalculation({
237
237
  }) {
238
238
  const from = 0;
239
239
  const to = 1;
240
+ const resolvedConfig = {
241
+ damping: config.damping ?? defaultSpringConfig.damping,
242
+ mass: config.mass ?? defaultSpringConfig.mass,
243
+ stiffness: config.stiffness ?? defaultSpringConfig.stiffness,
244
+ overshootClamping: config.overshootClamping ?? defaultSpringConfig.overshootClamping
245
+ };
240
246
  const cacheKey = [
241
247
  frame,
242
248
  fps,
243
- config.damping,
244
- config.mass,
245
- config.overshootClamping,
246
- config.stiffness
249
+ resolvedConfig.damping,
250
+ resolvedConfig.mass,
251
+ resolvedConfig.overshootClamping,
252
+ resolvedConfig.stiffness
247
253
  ].join("-");
248
254
  if (calculationCache[cacheKey]) {
249
255
  return calculationCache[cacheKey];
@@ -262,20 +268,14 @@ function springCalculation({
262
268
  animation = advance({
263
269
  animation,
264
270
  now: time,
265
- config: {
266
- ...defaultSpringConfig,
267
- ...config
268
- }
271
+ config: resolvedConfig
269
272
  });
270
273
  }
271
274
  if (unevenRest > 0) {
272
275
  animation = advance({
273
276
  animation,
274
277
  now: frameClamped / fps * 1000,
275
- config: {
276
- ...defaultSpringConfig,
277
- ...config
278
- }
278
+ config: resolvedConfig
279
279
  });
280
280
  }
281
281
  calculationCache[cacheKey] = animation;
@@ -750,7 +750,7 @@ var parseAxisRotationValue = (output) => {
750
750
  axisRotation: true
751
751
  };
752
752
  };
753
- var parseStringInterpolationValue = (output) => {
753
+ var parseStringInterpolationValue = (output, outputType) => {
754
754
  if (typeof output === "number") {
755
755
  if (!Number.isFinite(output)) {
756
756
  throw new Error(`outputRange must contain only finite numbers, but got [${output}]`);
@@ -763,8 +763,18 @@ var parseStringInterpolationValue = (output) => {
763
763
  axisRotation: false
764
764
  };
765
765
  }
766
+ if (outputType === "transform-origin") {
767
+ const transformOriginParts = output.trim().split(/\s+/);
768
+ if (transformOriginParts.length < 1 || transformOriginParts.length > 3 || transformOriginParts[0] === "") {
769
+ throw new TypeError(`String outputRange values must contain 1 to 3 components, but got "${output}"`);
770
+ }
771
+ return parseTransformOriginValue(output, transformOriginParts);
772
+ }
766
773
  const axisRotation = parseAxisRotationValue(output);
767
774
  if (axisRotation !== null) {
775
+ if (outputType !== undefined && outputType !== "rotate") {
776
+ throw new TypeError(`Cannot interpolate "${output}" as ${outputType} because it is a rotate value`);
777
+ }
768
778
  return axisRotation;
769
779
  }
770
780
  const parts = output.trim().split(/\s+/);
@@ -772,6 +782,9 @@ var parseStringInterpolationValue = (output) => {
772
782
  throw new TypeError(`String outputRange values must contain 1 to 3 components, but got "${output}"`);
773
783
  }
774
784
  if (parts.some((part) => transformOriginKeywords.has(part.toLowerCase()))) {
785
+ if (outputType !== undefined) {
786
+ throw new TypeError(`Cannot interpolate "${output}" as ${outputType} because it is a transform-origin value`);
787
+ }
775
788
  return parseTransformOriginValue(output, parts);
776
789
  }
777
790
  const parsed = parts.map((part) => parseStringInterpolationComponent(part, output));
@@ -781,6 +794,9 @@ var parseStringInterpolationValue = (output) => {
781
794
  throw new TypeError(`Cannot interpolate "${output}" because it mixes ${kind} and ${part.kind} values`);
782
795
  }
783
796
  }
797
+ if (outputType !== undefined && outputType !== kind) {
798
+ throw new TypeError(`Cannot interpolate "${output}" as ${outputType} because it is a ${kind} value`);
799
+ }
784
800
  if (kind === "scale") {
785
801
  const x = parsed[0].value;
786
802
  const y = parsed[1]?.value ?? x;
@@ -981,9 +997,10 @@ var interpolateString = ({
981
997
  input,
982
998
  inputRange,
983
999
  outputRange,
984
- options
1000
+ options,
1001
+ outputType
985
1002
  }) => {
986
- const initiallyParsedOutputRange = outputRange.map(parseStringInterpolationValue);
1003
+ const initiallyParsedOutputRange = outputRange.map((output) => parseStringInterpolationValue(output, outputType));
987
1004
  const hasAxisRotation = initiallyParsedOutputRange.some((parsed) => parsed.axisRotation);
988
1005
  const posterizedInput = options?.posterize === undefined ? input : Math.floor(input / options.posterize) * options.posterize;
989
1006
  const segmentIndex = inputRange.length === 1 ? 0 : findRange(posterizedInput, inputRange);
@@ -1063,6 +1080,36 @@ var interpolateString = ({
1063
1080
  axisRotation: hasAxisRotation
1064
1081
  });
1065
1082
  };
1083
+ var interpolateFontWeight = ({
1084
+ input,
1085
+ inputRange,
1086
+ outputRange,
1087
+ options
1088
+ }) => {
1089
+ const normalizedOutputRange = outputRange.map((output) => {
1090
+ if (typeof output === "string") {
1091
+ const lowerCaseOutput = output.toLowerCase();
1092
+ if (lowerCaseOutput === "normal") {
1093
+ return 400;
1094
+ }
1095
+ if (lowerCaseOutput === "bold") {
1096
+ return 700;
1097
+ }
1098
+ }
1099
+ const match = typeof output === "string" ? cssNumberRegex.exec(output) : null;
1100
+ const value = typeof output === "number" ? output : match !== null && match[2] === undefined ? Number(match[1]) : Number.NaN;
1101
+ if (!Number.isFinite(value) || value < 1 || value > 1000) {
1102
+ throw new TypeError(`Cannot interpolate font weight "${output}". Expected "normal", "bold", or a number between 1 and 1000`);
1103
+ }
1104
+ return value;
1105
+ });
1106
+ return interpolateNumber({
1107
+ input,
1108
+ inputRange,
1109
+ outputRange: normalizedOutputRange,
1110
+ options
1111
+ });
1112
+ };
1066
1113
  var interpolateDiscreteString = ({
1067
1114
  input,
1068
1115
  inputRange,
@@ -1194,6 +1241,12 @@ function assertValidInterpolateOutputOption(output) {
1194
1241
  }
1195
1242
  throw new Error(`output must be "linear" or "perceptual-scale", but got ${String(output)}`);
1196
1243
  }
1244
+ function assertValidInterpolateOutputType(outputType) {
1245
+ if (outputType === undefined || outputType === "font-weight" || outputType === "scale" || outputType === "translate" || outputType === "rotate" || outputType === "transform-origin") {
1246
+ return;
1247
+ }
1248
+ throw new Error(`outputType must be "font-weight", "scale", "translate", "rotate", or "transform-origin", but got ${String(outputType)}`);
1249
+ }
1197
1250
  function interpolate(input, inputRange, outputRange, options) {
1198
1251
  if (typeof input === "undefined") {
1199
1252
  throw new Error("input can not be undefined");
@@ -1212,26 +1265,48 @@ function interpolate(input, inputRange, outputRange, options) {
1212
1265
  assertValidInterpolateEasingOption(options?.easing, inputRange.length);
1213
1266
  assertValidInterpolatePosterizeOption(options?.posterize);
1214
1267
  assertValidInterpolateOutputOption(options?.output);
1268
+ assertValidInterpolateOutputType(options?.outputType);
1215
1269
  if (typeof input !== "number") {
1216
1270
  throw new TypeError("Cannot interpolate an input which is not a number");
1217
1271
  }
1218
1272
  if (!Array.isArray(outputRange)) {
1219
1273
  throw new Error("outputRange must contain only numbers");
1220
1274
  }
1275
+ const outputType = options?.outputType;
1276
+ if (outputType === "font-weight") {
1277
+ if (!outputRange.every((output) => typeof output === "number" || typeof output === "string")) {
1278
+ throw new TypeError("Font weight outputRange must contain only numbers or strings");
1279
+ }
1280
+ return interpolateFontWeight({
1281
+ input,
1282
+ inputRange,
1283
+ outputRange,
1284
+ options
1285
+ });
1286
+ }
1221
1287
  const hasStringOutput = outputRange.some((output) => typeof output === "string");
1288
+ if (outputType !== undefined && outputType !== "scale" && !hasStringOutput) {
1289
+ throw new TypeError(`${outputType} outputRange must contain strings with the appropriate CSS units`);
1290
+ }
1222
1291
  if (hasStringOutput) {
1223
1292
  if (!outputRange.every((output) => typeof output === "string" || typeof output === "number")) {
1224
1293
  throw new TypeError("outputRange must contain only numbers, or supported scale, translate, and rotate strings");
1225
1294
  }
1226
1295
  try {
1227
- return interpolateString({ input, inputRange, outputRange, options });
1296
+ return interpolateString({
1297
+ input,
1298
+ inputRange,
1299
+ outputRange,
1300
+ options,
1301
+ outputType
1302
+ });
1228
1303
  } catch (error) {
1229
1304
  if (!outputRange.every((output) => typeof output === "string")) {
1230
1305
  throw error;
1231
1306
  }
1232
1307
  const hasNonNumericString = outputRange.some((output) => {
1233
1308
  try {
1234
- parseStringInterpolationValue(output);
1309
+ parseStringInterpolationValue(output, outputType);
1235
1310
  return false;
1236
1311
  } catch (parseError) {
1237
1312
  return parseError instanceof UnsupportedStringInterpolationValueError;
@@ -1,5 +1,5 @@
1
1
  // src/version.ts
2
- var VERSION = "4.0.526";
2
+ var VERSION = "4.0.527";
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.526",
6
+ "version": "4.0.527",
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.5.4",
38
- "@remotion/eslint-config-internal": "4.0.526",
38
+ "@remotion/eslint-config-internal": "4.0.527",
39
39
  "eslint": "9.19.0",
40
40
  "@typescript/native-preview": "7.0.0-dev.20260217.1"
41
41
  },
@@ -1,11 +0,0 @@
1
- export type TNonceContext = {
2
- getNonce: () => number;
3
- };
4
- type NonceHistoryItem = [number, number];
5
- export type NonceHistory = NonceHistoryItem[];
6
- export type NonceHistoryContext = {
7
- get: () => NonceHistory;
8
- };
9
- export declare const NonceContext: import("react").Context<TNonceContext>;
10
- export declare const useNonce: () => NonceHistoryContext;
11
- export {};
package/dist/cjs/nonce.js DELETED
@@ -1,42 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.useNonce = exports.NonceContext = void 0;
4
- const react_1 = require("react");
5
- exports.NonceContext = (0, react_1.createContext)({
6
- getNonce: () => 0,
7
- });
8
- let fastRefreshNonce = 0;
9
- try {
10
- if (typeof __webpack_module__ !== 'undefined') {
11
- if (__webpack_module__.hot) {
12
- __webpack_module__.hot.addStatusHandler((status) => {
13
- if (status === 'idle') {
14
- fastRefreshNonce++;
15
- }
16
- });
17
- }
18
- }
19
- }
20
- catch (_a) {
21
- // __webpack_module__ may throw ReferenceError in some environments
22
- }
23
- const useNonce = () => {
24
- const context = (0, react_1.useContext)(exports.NonceContext);
25
- const nonce = context.getNonce();
26
- const nonceRef = (0, react_1.useRef)(nonce);
27
- nonceRef.current = nonce;
28
- const history = (0, react_1.useRef)([[fastRefreshNonce, nonce]]);
29
- const get = (0, react_1.useCallback)(() => {
30
- if (fastRefreshNonce !== history.current[history.current.length - 1][0]) {
31
- history.current = [
32
- ...history.current,
33
- [fastRefreshNonce, nonceRef.current],
34
- ];
35
- }
36
- return history.current;
37
- }, [history]);
38
- return (0, react_1.useMemo)(() => {
39
- return { get };
40
- }, [get]);
41
- };
42
- exports.useNonce = useNonce;