remotion 4.0.489 → 4.0.491

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.
@@ -965,26 +965,20 @@ var continueRenderInternal = ({
965
965
  if (typeof handle !== "number") {
966
966
  throw new TypeError("The parameter passed into continueRender() must be the return value of delayRender() which is a number. Got: " + JSON.stringify(handle));
967
967
  }
968
- scope.remotion_delayRenderHandles = scope.remotion_delayRenderHandles.filter((h) => {
969
- if (h === handle) {
970
- if (environment.isRendering && scope !== undefined) {
971
- if (!scope.remotion_delayRenderTimeouts[handle]) {
972
- return false;
973
- }
974
- const { label: label2, startTime, timeout } = scope.remotion_delayRenderTimeouts[handle];
975
- clearTimeout(timeout);
976
- const message = [
977
- label2 ? `"${label2}"` : "A handle",
978
- DELAY_RENDER_CLEAR_TOKEN,
979
- `${Date.now() - startTime}ms`
980
- ].filter(truthy).join(" ");
981
- Log.verbose({ logLevel, tag: "delayRender()" }, message);
982
- delete scope.remotion_delayRenderTimeouts[handle];
983
- }
984
- return false;
985
- }
986
- return true;
987
- });
968
+ const handleExists = scope.remotion_delayRenderHandles.includes(handle);
969
+ const timeoutEntry = scope.remotion_delayRenderTimeouts[handle];
970
+ if (handleExists && environment.isRendering && timeoutEntry) {
971
+ const { label: label2, startTime, timeout } = timeoutEntry;
972
+ clearTimeout(timeout);
973
+ const message = [
974
+ label2 ? `"${label2}"` : "A handle",
975
+ DELAY_RENDER_CLEAR_TOKEN,
976
+ `${Date.now() - startTime}ms`
977
+ ].filter(truthy).join(" ");
978
+ Log.verbose({ logLevel, tag: "delayRender()" }, message);
979
+ delete scope.remotion_delayRenderTimeouts[handle];
980
+ }
981
+ scope.remotion_delayRenderHandles = scope.remotion_delayRenderHandles.filter((h) => h !== handle);
988
982
  if (scope.remotion_delayRenderHandles.length === 0) {
989
983
  scope.remotion_renderReady = true;
990
984
  }
@@ -1291,7 +1285,7 @@ var addSequenceStackTraces = (component) => {
1291
1285
  };
1292
1286
 
1293
1287
  // src/version.ts
1294
- var VERSION = "4.0.489";
1288
+ var VERSION = "4.0.491";
1295
1289
 
1296
1290
  // src/multiple-versions-warning.ts
1297
1291
  var checkMultipleRemotionVersions = () => {
@@ -1731,7 +1725,8 @@ var transformSchema = {
1731
1725
  max: 100,
1732
1726
  step: 0.01,
1733
1727
  default: 1,
1734
- description: "Scale"
1728
+ description: "Scale",
1729
+ defaultKeyframeOutput: "perceptual-scale"
1735
1730
  },
1736
1731
  "style.rotate": {
1737
1732
  type: "rotation-css",
@@ -1969,7 +1964,7 @@ var SequenceManagerRefContext = React11.createContext({
1969
1964
  current: []
1970
1965
  });
1971
1966
  var makeSequencePropsSubscriptionKey = (key) => {
1972
- return `${key.nodePath.join(".")}.${key.sequenceKeys.join(".")}.${key.effectKeys.map((keys) => keys.join(".")).join(".")}`;
1967
+ return `${key.absolutePath}\x00${key.nodePath.join(".")}\x00${key.sequenceKeys.join(".")}\x00${key.effectKeys.map((keys) => keys.join(".")).join(".")}`;
1973
1968
  };
1974
1969
  var VisualModePropStatusesContext = React11.createContext({
1975
1970
  propStatuses: {}
@@ -2562,8 +2557,20 @@ var serializeStringInterpolationValue = ({
2562
2557
  }
2563
2558
  return values.slice(0, dimensions).map((value, index) => `${stringifyNumber(value)}${units[index]}`).join(" ");
2564
2559
  };
2560
+ var toSignedArea = (scale) => {
2561
+ if (scale === 0) {
2562
+ return 0;
2563
+ }
2564
+ return Math.sign(scale) * scale * scale;
2565
+ };
2566
+ var fromSignedArea = (area) => {
2567
+ if (area === 0) {
2568
+ return 0;
2569
+ }
2570
+ return Math.sign(area) * Math.sqrt(Math.abs(area));
2571
+ };
2565
2572
  function interpolateFunction(input, inputRange, outputRange, options) {
2566
- const { extrapolateLeft, extrapolateRight, easing } = options;
2573
+ const { extrapolateLeft, extrapolateRight, easing, output } = options;
2567
2574
  let result = input;
2568
2575
  const [inputMin, inputMax] = inputRange;
2569
2576
  const [outputMin, outputMax] = outputRange;
@@ -2594,7 +2601,13 @@ function interpolateFunction(input, inputRange, outputRange, options) {
2594
2601
  }
2595
2602
  result = (result - inputMin) / (inputMax - inputMin);
2596
2603
  result = easing(result);
2597
- result = result * (outputMax - outputMin) + outputMin;
2604
+ if (output === "perceptual-scale") {
2605
+ const signedAreaMin = toSignedArea(outputMin);
2606
+ const signedAreaMax = toSignedArea(outputMax);
2607
+ result = fromSignedArea(result * (signedAreaMax - signedAreaMin) + signedAreaMin);
2608
+ } else {
2609
+ result = result * (outputMax - outputMin) + outputMin;
2610
+ }
2598
2611
  return result;
2599
2612
  }
2600
2613
  function findRange(input, inputRange) {
@@ -2607,6 +2620,9 @@ function findRange(input, inputRange) {
2607
2620
  return i - 1;
2608
2621
  }
2609
2622
  var defaultEasing = (num) => num;
2623
+ var resolveOutputOption = (output) => {
2624
+ return output ?? "linear";
2625
+ };
2610
2626
  var shouldExtendRightForEasing = (easing) => {
2611
2627
  return easing.remotionShouldExtendRight === true;
2612
2628
  };
@@ -2628,12 +2644,14 @@ var interpolateSegment = ({
2628
2644
  outputRange,
2629
2645
  easing,
2630
2646
  extrapolateLeft,
2631
- extrapolateRight
2647
+ extrapolateRight,
2648
+ output
2632
2649
  }) => {
2633
2650
  return interpolateFunction(input, inputRange, outputRange, {
2634
2651
  easing,
2635
2652
  extrapolateLeft,
2636
- extrapolateRight: input > inputRange[1] && extrapolateRight === "clamp" && shouldExtendRightForEasing(easing) ? "extend" : extrapolateRight
2653
+ extrapolateRight: input > inputRange[1] && extrapolateRight === "clamp" && shouldExtendRightForEasing(easing) ? "extend" : extrapolateRight,
2654
+ output
2637
2655
  });
2638
2656
  };
2639
2657
  var interpolateNumber = ({
@@ -2642,6 +2660,7 @@ var interpolateNumber = ({
2642
2660
  outputRange,
2643
2661
  options
2644
2662
  }) => {
2663
+ const output = resolveOutputOption(options?.output);
2645
2664
  if (inputRange.length === 1) {
2646
2665
  return outputRange[0];
2647
2666
  }
@@ -2666,7 +2685,8 @@ var interpolateNumber = ({
2666
2685
  outputRange: [outputRange[range], outputRange[range + 1]],
2667
2686
  easing,
2668
2687
  extrapolateLeft,
2669
- extrapolateRight
2688
+ extrapolateRight,
2689
+ output
2670
2690
  });
2671
2691
  for (let segmentIndex = 0;segmentIndex < range; segmentIndex++) {
2672
2692
  const previousEasing = resolveEasingForSegment({
@@ -2686,7 +2706,8 @@ var interpolateNumber = ({
2686
2706
  outputRange: [outputRange[segmentIndex], outputRange[segmentIndex + 1]],
2687
2707
  easing: previousEasing,
2688
2708
  extrapolateLeft,
2689
- extrapolateRight: "extend"
2709
+ extrapolateRight: "extend",
2710
+ output
2690
2711
  });
2691
2712
  result += continuedSegmentValue - outputRange[segmentIndex + 1];
2692
2713
  }
@@ -2734,14 +2755,18 @@ var interpolateString = ({
2734
2755
  }
2735
2756
  }
2736
2757
  }
2737
- return serializeStringInterpolationValue({
2738
- kind,
2739
- values: [0, 0, 0].map((_, axis) => interpolateNumber({
2758
+ const values = [0, 0, 0];
2759
+ for (let axis = 0;axis < dimensions; axis++) {
2760
+ values[axis] = interpolateNumber({
2740
2761
  input,
2741
2762
  inputRange,
2742
2763
  outputRange: parsedOutputRange.map((parsed) => parsed.values[axis]),
2743
2764
  options
2744
- })),
2765
+ });
2766
+ }
2767
+ return serializeStringInterpolationValue({
2768
+ kind,
2769
+ values,
2745
2770
  units,
2746
2771
  dimensions
2747
2772
  });
@@ -2825,6 +2850,12 @@ function assertValidInterpolatePosterizeOption(posterize) {
2825
2850
  throw new Error(`posterize must be a positive finite number, but got ${posterize}`);
2826
2851
  }
2827
2852
  }
2853
+ function assertValidInterpolateOutputOption(output) {
2854
+ if (output === undefined || output === "linear" || output === "perceptual-scale") {
2855
+ return;
2856
+ }
2857
+ throw new Error(`output must be "linear" or "perceptual-scale", but got ${String(output)}`);
2858
+ }
2828
2859
  function interpolate(input, inputRange, outputRange, options) {
2829
2860
  if (typeof input === "undefined") {
2830
2861
  throw new Error("input can not be undefined");
@@ -2842,6 +2873,7 @@ function interpolate(input, inputRange, outputRange, options) {
2842
2873
  checkValidInputRange(inputRange);
2843
2874
  assertValidInterpolateEasingOption(options?.easing, inputRange.length);
2844
2875
  assertValidInterpolatePosterizeOption(options?.posterize);
2876
+ assertValidInterpolateOutputOption(options?.output);
2845
2877
  if (typeof input !== "number") {
2846
2878
  throw new TypeError("Cannot interpolate an input which is not a number");
2847
2879
  }
@@ -3802,6 +3834,7 @@ var interpolateKeyframedStatus = ({
3802
3834
  easing: easing.map((e) => easingToFn({ easing: e, forceSpringAllowTail })),
3803
3835
  extrapolateLeft: clamping.left,
3804
3836
  extrapolateRight: clamping.right,
3837
+ output: status.output,
3805
3838
  posterize: status.posterize
3806
3839
  });
3807
3840
  } catch {
@@ -4051,7 +4084,7 @@ var getFlatSchemaWithAllKeys = (schema) => {
4051
4084
  const out = {};
4052
4085
  const addKey = (key, field) => {
4053
4086
  if (key in out) {
4054
- throw new Error(`Duplicate key "${key}" in schema: discriminated union variants must not share keys`);
4087
+ return;
4055
4088
  }
4056
4089
  out[key] = field;
4057
4090
  };
@@ -4598,6 +4631,7 @@ var RegularSequenceRefForwardingFunction = ({
4598
4631
  src: isMedia.data.src,
4599
4632
  getStack: () => stackRef.current,
4600
4633
  startMediaFrom: startMediaFrom ?? isMedia.data.startMediaFrom,
4634
+ mediaFrameAtSequenceZero,
4601
4635
  volume: isMedia.data.volumes,
4602
4636
  refForOutline: refForOutline ?? null,
4603
4637
  isInsideSeries,
@@ -4661,6 +4695,7 @@ var RegularSequenceRefForwardingFunction = ({
4661
4695
  isInsideSeries,
4662
4696
  registeredFrozenFrame,
4663
4697
  startMediaFrom,
4698
+ mediaFrameAtSequenceZero,
4664
4699
  frozenMediaFrame
4665
4700
  ]);
4666
4701
  const endThreshold = Math.ceil(cumulatedFrom + from + durationInFrames - 1);
@@ -6740,7 +6775,9 @@ var SharedAudioTagsContextProvider = ({ children, numberOfAudioTags }) => {
6740
6775
  return;
6741
6776
  }
6742
6777
  if (data === undefined) {
6743
- current.src = EMPTY_AUDIO;
6778
+ if (current.src !== EMPTY_AUDIO) {
6779
+ current.src = EMPTY_AUDIO;
6780
+ }
6744
6781
  return;
6745
6782
  }
6746
6783
  if (!data) {
@@ -6809,7 +6846,7 @@ var SharedAudioTagsContextProvider = ({ children, numberOfAudioTags }) => {
6809
6846
  if (prevA.id === id) {
6810
6847
  const isTheSame = compareProps(aud, prevA.props) && prevA.premounting === premounting && prevA.postmounting === postmounting;
6811
6848
  if (isTheSame) {
6812
- return prevA;
6849
+ return prevA.audioMounted === audioMounted ? prevA : { ...prevA, audioMounted };
6813
6850
  }
6814
6851
  changed = true;
6815
6852
  return {
@@ -6821,7 +6858,7 @@ var SharedAudioTagsContextProvider = ({ children, numberOfAudioTags }) => {
6821
6858
  audioMounted
6822
6859
  };
6823
6860
  }
6824
- return prevA;
6861
+ return prevA.audioMounted === audioMounted ? prevA : { ...prevA, audioMounted };
6825
6862
  });
6826
6863
  if (changed) {
6827
6864
  rerenderAudios();
@@ -6860,16 +6897,19 @@ var SharedAudioTagsContextProvider = ({ children, numberOfAudioTags }) => {
6860
6897
  unregisterAudio,
6861
6898
  updateAudio
6862
6899
  ]);
6900
+ const sharedAudioTagElements = useMemo21(() => {
6901
+ return refs.map(({ id, ref }) => {
6902
+ return /* @__PURE__ */ jsx19("audio", {
6903
+ ref,
6904
+ preload: "metadata",
6905
+ src: EMPTY_AUDIO
6906
+ }, id);
6907
+ });
6908
+ }, [refs]);
6863
6909
  return /* @__PURE__ */ jsxs2(SharedAudioTagsContext.Provider, {
6864
6910
  value: audioTagsValue,
6865
6911
  children: [
6866
- refs.map(({ id, ref }) => {
6867
- return /* @__PURE__ */ jsx19("audio", {
6868
- ref,
6869
- preload: "metadata",
6870
- src: EMPTY_AUDIO
6871
- }, id);
6872
- }),
6912
+ sharedAudioTagElements,
6873
6913
  children
6874
6914
  ]
6875
6915
  });
@@ -7351,6 +7391,7 @@ var useMediaInTimeline = ({
7351
7391
  showInTimeline: true,
7352
7392
  nonce: nonce.get(),
7353
7393
  startMediaFrom: 0 - startsAt,
7394
+ mediaFrameAtSequenceZero: null,
7354
7395
  doesVolumeChange,
7355
7396
  loopDisplay,
7356
7397
  playbackRate,
@@ -9082,16 +9123,16 @@ var isMissingPaintRecordError = (error2) => {
9082
9123
  return error2 instanceof DOMException && error2.name === "InvalidStateError";
9083
9124
  };
9084
9125
  var missingPaintRecordMessage = "HtmlInCanvas: Expected the element to be inside the viewport during rendering, but Chrome had no cached paint record for it.";
9085
- var resizeOffscreenCanvas = ({
9086
- offscreen,
9126
+ var resizePaintTarget = ({
9127
+ target,
9087
9128
  width,
9088
9129
  height
9089
9130
  }) => {
9090
- if (offscreen.width !== width) {
9091
- offscreen.width = width;
9131
+ if (target.width !== width) {
9132
+ target.width = width;
9092
9133
  }
9093
- if (offscreen.height !== height) {
9094
- offscreen.height = height;
9134
+ if (target.height !== height) {
9135
+ target.height = height;
9095
9136
  }
9096
9137
  };
9097
9138
  var defaultOnPaint = ({
@@ -9107,7 +9148,7 @@ var defaultOnPaint = ({
9107
9148
  const transform = ctx.drawElementImage(elementImage, 0, 0);
9108
9149
  element.style.transform = transform.toString();
9109
9150
  };
9110
- var HtmlInCanvasAncestorContext = createContext23(false);
9151
+ var HtmlInCanvasAncestorContext = createContext23(null);
9111
9152
  var HtmlInCanvasContent = forwardRef9(({
9112
9153
  width,
9113
9154
  height,
@@ -9119,20 +9160,22 @@ var HtmlInCanvasContent = forwardRef9(({
9119
9160
  controls,
9120
9161
  style
9121
9162
  }, ref) => {
9122
- const isInsideAncestorHtmlInCanvas = useContext31(HtmlInCanvasAncestorContext);
9163
+ const ancestor = useContext31(HtmlInCanvasAncestorContext);
9123
9164
  assertHtmlInCanvasDimensions(width, height);
9124
9165
  const resolvedPixelDensity = resolveHtmlInCanvasPixelDensity(pixelDensity);
9125
9166
  const canvasWidth = Math.ceil(width * resolvedPixelDensity);
9126
9167
  const canvasHeight = Math.ceil(height * resolvedPixelDensity);
9127
9168
  const { continueRender: continueRender2, cancelRender: cancelRender2 } = useDelayRender();
9128
- const { isRendering } = useRemotionEnvironment();
9169
+ const { isClientSideRendering, isRendering } = useRemotionEnvironment();
9170
+ const canRetryMissingPaintRecord = !isRendering || isClientSideRendering;
9171
+ const usesDirectLayoutCanvas = onPaint === undefined && onInit === undefined;
9129
9172
  if (!isHtmlInCanvasSupported()) {
9130
9173
  cancelRender2(new Error(HTML_IN_CANVAS_UNSUPPORTED_MESSAGE));
9131
9174
  }
9132
9175
  const canvas2dRef = useRef22(null);
9133
- const offscreenRef = useRef22(null);
9176
+ const paintTargetRef = useRef22(null);
9134
9177
  const divRef = useRef22(null);
9135
- const canvasSizeKey = `${width}x${height}@${resolvedPixelDensity}`;
9178
+ const canvasSizeKey = `${width}x${height}@${resolvedPixelDensity}-${usesDirectLayoutCanvas ? "direct" : "offscreen"}`;
9136
9179
  const setLayoutCanvasRef = useCallback16((node) => {
9137
9180
  canvas2dRef.current = node;
9138
9181
  if (typeof ref === "function") {
@@ -9155,17 +9198,19 @@ var HtmlInCanvasContent = forwardRef9(({
9155
9198
  const initializedRef = useRef22(false);
9156
9199
  const onInitCleanupRef = useRef22(null);
9157
9200
  const unmountedRef = useRef22(false);
9201
+ const ancestorRef = useRef22(ancestor);
9202
+ ancestorRef.current = ancestor;
9158
9203
  const onPaintCb = useCallback16(async () => {
9159
9204
  const element = divRef.current;
9160
9205
  if (!element) {
9161
9206
  throw new Error("Canvas or scene element not found");
9162
9207
  }
9163
- const offscreen = offscreenRef.current;
9164
- if (!offscreen) {
9165
- throw new Error("HtmlInCanvas: offscreen canvas not ready (transferControlToOffscreen failed or canvas is remounting)");
9208
+ const paintTarget = paintTargetRef.current;
9209
+ if (!paintTarget) {
9210
+ throw new Error("HtmlInCanvas: paint target is not ready because the canvas is remounting");
9166
9211
  }
9167
- resizeOffscreenCanvas({
9168
- offscreen,
9212
+ resizePaintTarget({
9213
+ target: paintTarget,
9169
9214
  width: canvasWidth,
9170
9215
  height: canvasHeight
9171
9216
  });
@@ -9176,22 +9221,30 @@ var HtmlInCanvasContent = forwardRef9(({
9176
9221
  }
9177
9222
  const handle = delayRender("onPaint");
9178
9223
  if (!initializedRef.current) {
9179
- let initImage = null;
9180
- try {
9181
- initImage = placeholderCanvas.captureElementImage(element);
9182
- } catch (error2) {
9183
- if (isMissingPaintRecordError(error2) && !isRendering) {} else if (isMissingPaintRecordError(error2)) {
9184
- throw new Error(missingPaintRecordMessage);
9185
- } else {
9224
+ const currentOnInit = onInitRef.current;
9225
+ if (!currentOnInit) {
9226
+ initializedRef.current = true;
9227
+ } else {
9228
+ let initImage;
9229
+ try {
9230
+ initImage = placeholderCanvas.captureElementImage(element);
9231
+ } catch (error2) {
9232
+ if (isMissingPaintRecordError(error2) && canRetryMissingPaintRecord) {
9233
+ continueRender2(handle);
9234
+ return;
9235
+ }
9236
+ if (isMissingPaintRecordError(error2)) {
9237
+ throw new Error(missingPaintRecordMessage);
9238
+ }
9186
9239
  throw error2;
9187
9240
  }
9188
- }
9189
- if (initImage) {
9190
9241
  initializedRef.current = true;
9191
- const currentOnInit = onInitRef.current;
9192
- if (currentOnInit) {
9242
+ try {
9243
+ if (paintTarget instanceof HTMLCanvasElement) {
9244
+ throw new Error("HtmlInCanvas: onInit requires an OffscreenCanvas paint target");
9245
+ }
9193
9246
  const cleanup = await currentOnInit({
9194
- canvas: offscreen,
9247
+ canvas: paintTarget,
9195
9248
  element,
9196
9249
  elementImage: initImage,
9197
9250
  pixelDensity: resolvedPixelDensity
@@ -9204,15 +9257,16 @@ var HtmlInCanvasContent = forwardRef9(({
9204
9257
  } else {
9205
9258
  onInitCleanupRef.current = cleanup;
9206
9259
  }
9260
+ } finally {
9261
+ initImage.close();
9207
9262
  }
9208
9263
  }
9209
9264
  }
9210
- const handler = onPaintRef.current ?? defaultOnPaint;
9211
9265
  let elImage;
9212
9266
  try {
9213
9267
  elImage = placeholderCanvas.captureElementImage(element);
9214
9268
  } catch (error2) {
9215
- if (isMissingPaintRecordError(error2) && !isRendering) {
9269
+ if (isMissingPaintRecordError(error2) && canRetryMissingPaintRecord) {
9216
9270
  continueRender2(handle);
9217
9271
  return;
9218
9272
  }
@@ -9221,20 +9275,41 @@ var HtmlInCanvasContent = forwardRef9(({
9221
9275
  }
9222
9276
  throw error2;
9223
9277
  }
9224
- await handler({
9225
- canvas: offscreen,
9226
- element,
9227
- elementImage: elImage,
9228
- pixelDensity: resolvedPixelDensity
9229
- });
9230
- await runEffectChain({
9231
- state: chainState.get(canvasWidth, canvasHeight),
9232
- source: offscreen,
9233
- effects: effectsRef.current,
9234
- output: offscreen,
9235
- width: canvasWidth,
9236
- height: canvasHeight
9237
- });
9278
+ try {
9279
+ const currentOnPaint = onPaintRef.current;
9280
+ if (currentOnPaint) {
9281
+ if (paintTarget instanceof HTMLCanvasElement) {
9282
+ throw new Error("HtmlInCanvas: onPaint requires an OffscreenCanvas paint target");
9283
+ }
9284
+ const paintResult = currentOnPaint({
9285
+ canvas: paintTarget,
9286
+ element,
9287
+ elementImage: elImage,
9288
+ pixelDensity: resolvedPixelDensity
9289
+ });
9290
+ if (paintResult) {
9291
+ await paintResult;
9292
+ }
9293
+ } else {
9294
+ defaultOnPaint({
9295
+ canvas: paintTarget,
9296
+ element,
9297
+ elementImage: elImage,
9298
+ pixelDensity: resolvedPixelDensity
9299
+ });
9300
+ }
9301
+ await runEffectChain({
9302
+ state: chainState.get(canvasWidth, canvasHeight),
9303
+ source: paintTarget,
9304
+ effects: effectsRef.current,
9305
+ output: paintTarget,
9306
+ width: canvasWidth,
9307
+ height: canvasHeight
9308
+ });
9309
+ } finally {
9310
+ elImage.close();
9311
+ }
9312
+ ancestorRef.current?.requestParentPaint();
9238
9313
  continueRender2(handle);
9239
9314
  } catch (error2) {
9240
9315
  cancelRender2(error2);
@@ -9246,7 +9321,7 @@ var HtmlInCanvasContent = forwardRef9(({
9246
9321
  continueRender2,
9247
9322
  cancelRender2,
9248
9323
  resolvedPixelDensity,
9249
- isRendering
9324
+ canRetryMissingPaintRecord
9250
9325
  ]);
9251
9326
  useLayoutEffect9(() => {
9252
9327
  const placeholder = canvas2dRef.current;
@@ -9254,10 +9329,10 @@ var HtmlInCanvasContent = forwardRef9(({
9254
9329
  throw new Error("Canvas not found");
9255
9330
  }
9256
9331
  placeholder.layoutSubtree = true;
9257
- const offscreen = placeholder.transferControlToOffscreen();
9258
- offscreenRef.current = offscreen;
9259
- resizeOffscreenCanvas({
9260
- offscreen,
9332
+ const paintTarget = usesDirectLayoutCanvas ? placeholder : placeholder.transferControlToOffscreen();
9333
+ paintTargetRef.current = paintTarget;
9334
+ resizePaintTarget({
9335
+ target: paintTarget,
9261
9336
  width: canvasWidth,
9262
9337
  height: canvasHeight
9263
9338
  });
@@ -9266,13 +9341,19 @@ var HtmlInCanvasContent = forwardRef9(({
9266
9341
  placeholder.addEventListener("paint", onPaintCb);
9267
9342
  return () => {
9268
9343
  placeholder.removeEventListener("paint", onPaintCb);
9269
- offscreenRef.current = null;
9344
+ paintTargetRef.current = null;
9270
9345
  initializedRef.current = false;
9271
9346
  unmountedRef.current = true;
9272
9347
  onInitCleanupRef.current?.();
9273
9348
  onInitCleanupRef.current = null;
9274
9349
  };
9275
- }, [onPaintCb, cancelRender2, canvasWidth, canvasHeight]);
9350
+ }, [
9351
+ onPaintCb,
9352
+ cancelRender2,
9353
+ canvasWidth,
9354
+ canvasHeight,
9355
+ usesDirectLayoutCanvas
9356
+ ]);
9276
9357
  const onPaintChangedRef = useRef22(false);
9277
9358
  useLayoutEffect9(() => {
9278
9359
  if (!onPaintChangedRef.current) {
@@ -9311,11 +9392,15 @@ var HtmlInCanvasContent = forwardRef9(({
9311
9392
  ...style ?? {}
9312
9393
  };
9313
9394
  }, [height, style, width]);
9314
- if (isInsideAncestorHtmlInCanvas) {
9315
- throw new Error("<HtmlInCanvas> effects cannot be nested together. Chrome will only display the outer effect. Consider merging the effects into one if you can.");
9316
- }
9395
+ const ancestorValue = useMemo30(() => {
9396
+ return {
9397
+ requestParentPaint: () => {
9398
+ canvas2dRef.current?.requestPaint?.();
9399
+ }
9400
+ };
9401
+ }, []);
9317
9402
  return /* @__PURE__ */ jsx25(HtmlInCanvasAncestorContext.Provider, {
9318
- value: true,
9403
+ value: ancestorValue,
9319
9404
  children: /* @__PURE__ */ jsx25("canvas", {
9320
9405
  ref: setLayoutCanvasRef,
9321
9406
  width: canvasWidth,
@@ -10249,6 +10334,22 @@ addSequenceStackTraces(Img);
10249
10334
  // src/Interactive.tsx
10250
10335
  import React29, { forwardRef as forwardRef12, useCallback as useCallback20, useRef as useRef25 } from "react";
10251
10336
  import { jsx as jsx29 } from "react/jsx-runtime";
10337
+ var sourcePathToIdentityPrefix = (packageName) => {
10338
+ if (packageName === "remotion") {
10339
+ return "dev.remotion.remotion";
10340
+ }
10341
+ if (packageName.startsWith("@remotion/")) {
10342
+ const normalizedPackageName = packageName.slice("@remotion/".length).replace(/-([a-z])/g, (_, char) => char.toUpperCase());
10343
+ return `dev.remotion.${normalizedPackageName}`;
10344
+ }
10345
+ throw new Error(`Unsupported Remotion package name: ${packageName}`);
10346
+ };
10347
+ var makeRemotionComponentIdentity = ({
10348
+ packageName,
10349
+ componentName
10350
+ }) => {
10351
+ return `${sourcePathToIdentityPrefix(packageName)}.${componentName}`;
10352
+ };
10252
10353
  var interactiveElementSchema = {
10253
10354
  ...baseSchema,
10254
10355
  ...transformSchema,
@@ -10262,6 +10363,11 @@ var setRef = (ref, value) => {
10262
10363
  ref.current = value;
10263
10364
  }
10264
10365
  };
10366
+ var withSchema = (options) => {
10367
+ const Wrapped = withInteractivitySchema(options);
10368
+ addSequenceStackTraces(Wrapped);
10369
+ return Wrapped;
10370
+ };
10265
10371
  var makeInteractiveElement = (tag, displayName) => {
10266
10372
  const Inner = forwardRef12((propsWithControls, ref) => {
10267
10373
  const {
@@ -10301,15 +10407,17 @@ var makeInteractiveElement = (tag, displayName) => {
10301
10407
  });
10302
10408
  });
10303
10409
  Inner.displayName = displayName;
10304
- const Wrapped = withInteractivitySchema({
10410
+ const Wrapped = withSchema({
10305
10411
  Component: Inner,
10306
10412
  componentName: displayName,
10307
- componentIdentity: `dev.remotion.remotion.${displayName.slice(1, -1)}`,
10413
+ componentIdentity: makeRemotionComponentIdentity({
10414
+ packageName: "remotion",
10415
+ componentName: displayName.slice(1, -1)
10416
+ }),
10308
10417
  schema: interactiveElementSchema,
10309
10418
  supportsEffects: false
10310
10419
  });
10311
10420
  Wrapped.displayName = displayName;
10312
- addSequenceStackTraces(Wrapped);
10313
10421
  return Wrapped;
10314
10422
  };
10315
10423
  var Interactive = {
@@ -10318,7 +10426,8 @@ var Interactive = {
10318
10426
  textSchema,
10319
10427
  premountSchema,
10320
10428
  sequenceSchema,
10321
- withSchema: withInteractivitySchema,
10429
+ withSchema,
10430
+ _internalMakeRemotionComponentIdentity: makeRemotionComponentIdentity,
10322
10431
  A: makeInteractiveElement("a", "<Interactive.A>"),
10323
10432
  Article: makeInteractiveElement("article", "<Interactive.Article>"),
10324
10433
  Aside: makeInteractiveElement("aside", "<Interactive.Aside>"),
@@ -11912,8 +12021,7 @@ var Internals = {
11912
12021
  fromField
11913
12022
  };
11914
12023
  // src/series/index.tsx
11915
- import {
11916
- Children,
12024
+ import React41, {
11917
12025
  forwardRef as forwardRef14,
11918
12026
  useMemo as useMemo38
11919
12027
  } from "react";
@@ -11932,67 +12040,131 @@ var flattenChildren = (children) => {
11932
12040
  };
11933
12041
 
11934
12042
  // src/series/index.tsx
11935
- import { jsx as jsx37 } from "react/jsx-runtime";
11936
- var SeriesSequenceRefForwardingFunction = ({ children }, _ref) => {
12043
+ import { jsx as jsx37, jsxs as jsxs3, Fragment } from "react/jsx-runtime";
12044
+ var seriesSequenceSchema = {
12045
+ durationInFrames: Interactive.baseSchema.durationInFrames,
12046
+ name: Interactive.sequenceSchema.name,
12047
+ hidden: Interactive.sequenceSchema.hidden,
12048
+ showInTimeline: Interactive.sequenceSchema.showInTimeline,
12049
+ freeze: Interactive.baseSchema.freeze,
12050
+ layout: Interactive.sequenceSchema.layout
12051
+ };
12052
+ var SeriesSequenceInner = forwardRef14(({
12053
+ offset = 0,
12054
+ className = "",
12055
+ stack = null,
12056
+ _remotionInternalRender = null,
12057
+ ...props2
12058
+ }, ref) => {
11937
12059
  useRequireToBeInsideSeries();
12060
+ if (_remotionInternalRender) {
12061
+ return _remotionInternalRender({ ...props2, offset, className: className || undefined, stack }, ref);
12062
+ }
11938
12063
  return /* @__PURE__ */ jsx37(IsNotInsideSeriesProvider, {
11939
- children
12064
+ children: props2.children
11940
12065
  });
11941
- };
11942
- var SeriesSequence = forwardRef14(SeriesSequenceRefForwardingFunction);
12066
+ });
12067
+ var SeriesSequence = Interactive.withSchema({
12068
+ Component: SeriesSequenceInner,
12069
+ componentName: "<Series.Sequence>",
12070
+ componentIdentity: "dev.remotion.remotion.Series.Sequence",
12071
+ schema: seriesSequenceSchema,
12072
+ supportsEffects: false
12073
+ });
11943
12074
  var SequenceWithoutSchemaWithRef = SequenceWithoutSchema;
12075
+ var validateSeriesSequenceProps = ({
12076
+ durationInFrames,
12077
+ offset: offsetProp,
12078
+ index,
12079
+ childrenLength
12080
+ }) => {
12081
+ const debugInfo = `index = ${index}, duration = ${durationInFrames}`;
12082
+ if (index !== childrenLength - 1 || durationInFrames !== Infinity) {
12083
+ validateDurationInFrames(durationInFrames, {
12084
+ component: `of a <Series.Sequence /> component`,
12085
+ allowFloats: true
12086
+ });
12087
+ }
12088
+ const offset = offsetProp ?? 0;
12089
+ if (Number.isNaN(offset)) {
12090
+ throw new TypeError(`The "offset" property of a <Series.Sequence /> must not be NaN, but got NaN (${debugInfo}).`);
12091
+ }
12092
+ if (!Number.isFinite(offset)) {
12093
+ throw new TypeError(`The "offset" property of a <Series.Sequence /> must be finite, but got ${offset} (${debugInfo}).`);
12094
+ }
12095
+ if (offset % 1 !== 0) {
12096
+ throw new TypeError(`The "offset" property of a <Series.Sequence /> must be finite, but got ${offset} (${debugInfo}).`);
12097
+ }
12098
+ return offset;
12099
+ };
11944
12100
  var SeriesInner = (props2) => {
11945
12101
  const childrenValue = useMemo38(() => {
11946
- let startFrame = 0;
11947
12102
  const flattenedChildren = flattenChildren(props2.children);
11948
- return Children.map(flattenedChildren, (child, i) => {
12103
+ const renderChildren = (i, startFrame) => {
12104
+ if (i === flattenedChildren.length) {
12105
+ return null;
12106
+ }
12107
+ const child = flattenedChildren[i];
11949
12108
  const castedChild = child;
11950
12109
  if (typeof castedChild === "string") {
11951
12110
  if (castedChild.trim() === "") {
11952
- return null;
12111
+ return renderChildren(i + 1, startFrame);
11953
12112
  }
11954
12113
  throw new TypeError(`The <Series /> component only accepts a list of <Series.Sequence /> components as its children, but you passed a string "${castedChild}"`);
11955
12114
  }
11956
12115
  if (castedChild.type !== SeriesSequence) {
11957
12116
  throw new TypeError(`The <Series /> component only accepts a list of <Series.Sequence /> components as its children, but got ${castedChild} instead`);
11958
12117
  }
11959
- const debugInfo = `index = ${i}, duration = ${castedChild.props.durationInFrames}`;
11960
- const durationInFramesProp = castedChild.props.durationInFrames;
11961
- const {
11962
- durationInFrames,
11963
- children: _children,
11964
- from,
11965
- name,
11966
- ...passedProps
11967
- } = castedChild.props;
11968
- if (i !== flattenedChildren.length - 1 || durationInFramesProp !== Infinity) {
11969
- validateDurationInFrames(durationInFramesProp, {
11970
- component: `of a <Series.Sequence /> component`,
11971
- allowFloats: true
11972
- });
11973
- }
11974
- const offset = castedChild.props.offset ?? 0;
11975
- if (Number.isNaN(offset)) {
11976
- throw new TypeError(`The "offset" property of a <Series.Sequence /> must not be NaN, but got NaN (${debugInfo}).`);
11977
- }
11978
- if (!Number.isFinite(offset)) {
11979
- throw new TypeError(`The "offset" property of a <Series.Sequence /> must be finite, but got ${offset} (${debugInfo}).`);
11980
- }
11981
- if (offset % 1 !== 0) {
11982
- throw new TypeError(`The "offset" property of a <Series.Sequence /> must be finite, but got ${offset} (${debugInfo}).`);
11983
- }
11984
- const currentStartFrame = startFrame + offset;
11985
- startFrame += durationInFramesProp + offset;
11986
- return /* @__PURE__ */ jsx37(SequenceWithoutSchemaWithRef, {
11987
- ref: castedChild.ref,
11988
- name: name || "<Series.Sequence>",
11989
- _remotionInternalDocumentationLink: name ? undefined : "https://www.remotion.dev/docs/series",
11990
- from: currentStartFrame,
11991
- durationInFrames: durationInFramesProp,
11992
- ...passedProps,
11993
- children: child
12118
+ const castedElement = castedChild;
12119
+ validateSeriesSequenceProps({
12120
+ durationInFrames: castedElement.props.durationInFrames,
12121
+ offset: castedElement.props.offset,
12122
+ index: i,
12123
+ childrenLength: flattenedChildren.length
11994
12124
  });
11995
- });
12125
+ return React41.cloneElement(castedElement, {
12126
+ _remotionInternalRender: (resolvedProps, ref) => {
12127
+ const durationInFramesProp = resolvedProps.durationInFrames;
12128
+ const {
12129
+ durationInFrames: _durationInFrames,
12130
+ children: sequenceChildren,
12131
+ offset: offsetProp,
12132
+ controls,
12133
+ stack,
12134
+ from: _from,
12135
+ name,
12136
+ ...passedProps
12137
+ } = resolvedProps;
12138
+ const offset = validateSeriesSequenceProps({
12139
+ durationInFrames: durationInFramesProp,
12140
+ offset: offsetProp,
12141
+ index: i,
12142
+ childrenLength: flattenedChildren.length
12143
+ });
12144
+ const currentStartFrame = startFrame + offset;
12145
+ const nextStartFrame = startFrame + durationInFramesProp + offset;
12146
+ return /* @__PURE__ */ jsxs3(Fragment, {
12147
+ children: [
12148
+ /* @__PURE__ */ jsx37(SequenceWithoutSchemaWithRef, {
12149
+ ref,
12150
+ name: name || "<Series.Sequence>",
12151
+ _remotionInternalDocumentationLink: name ? undefined : "https://www.remotion.dev/docs/series",
12152
+ _remotionInternalStack: stack ?? undefined,
12153
+ controls: controls ?? undefined,
12154
+ from: currentStartFrame,
12155
+ durationInFrames: durationInFramesProp,
12156
+ ...passedProps,
12157
+ children: /* @__PURE__ */ jsx37(IsNotInsideSeriesProvider, {
12158
+ children: sequenceChildren
12159
+ })
12160
+ }),
12161
+ renderChildren(i + 1, nextStartFrame)
12162
+ ]
12163
+ });
12164
+ }
12165
+ });
12166
+ };
12167
+ return renderChildren(0, 0);
11996
12168
  }, [props2.children]);
11997
12169
  return /* @__PURE__ */ jsx37(IsInsideSeriesContainer, {
11998
12170
  children: /* @__PURE__ */ jsx37(Sequence, {