remotion 4.0.498 → 4.0.500

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/dist/cjs/CompositionManager.d.ts +0 -1
  2. package/dist/cjs/HtmlInCanvas.d.ts +43 -3
  3. package/dist/cjs/HtmlInCanvas.js +29 -2
  4. package/dist/cjs/Img.d.ts +43 -3
  5. package/dist/cjs/Img.js +15 -5
  6. package/dist/cjs/Interactive.d.ts +118 -0
  7. package/dist/cjs/Interactive.js +28 -9
  8. package/dist/cjs/Sequence.d.ts +4 -0
  9. package/dist/cjs/Sequence.js +22 -7
  10. package/dist/cjs/TimelineContext.d.ts +0 -1
  11. package/dist/cjs/TimelineContext.js +1 -4
  12. package/dist/cjs/animated-image/AnimatedImage.d.ts +41 -1
  13. package/dist/cjs/animated-image/AnimatedImage.js +12 -2
  14. package/dist/cjs/animated-image/props.d.ts +2 -2
  15. package/dist/cjs/canvas-image/CanvasImage.d.ts +42 -1
  16. package/dist/cjs/canvas-image/CanvasImage.js +12 -2
  17. package/dist/cjs/canvas-image/props.d.ts +6 -2
  18. package/dist/cjs/effects/Solid.d.ts +43 -3
  19. package/dist/cjs/effects/Solid.js +12 -2
  20. package/dist/cjs/index.d.ts +1 -1
  21. package/dist/cjs/interactivity-schema.d.ts +239 -0
  22. package/dist/cjs/interactivity-schema.js +70 -1
  23. package/dist/cjs/internals.d.ts +127 -1
  24. package/dist/cjs/internals.js +5 -0
  25. package/dist/cjs/no-react.d.ts +40 -0
  26. package/dist/cjs/sequence-crop.d.ts +19 -0
  27. package/dist/cjs/sequence-crop.js +45 -0
  28. package/dist/cjs/use-crop-style.d.ts +6 -0
  29. package/dist/cjs/use-crop-style.js +19 -0
  30. package/dist/cjs/use-media-in-timeline.d.ts +0 -1
  31. package/dist/cjs/use-media-in-timeline.js +1 -7
  32. package/dist/cjs/version.d.ts +1 -1
  33. package/dist/cjs/version.js +1 -1
  34. package/dist/cjs/with-interactivity-schema.js +4 -2
  35. package/dist/esm/index.mjs +408 -140
  36. package/dist/esm/no-react.mjs +67 -0
  37. package/dist/esm/version.mjs +1 -1
  38. package/package.json +3 -3
@@ -72,7 +72,6 @@ export type TSequence = {
72
72
  displayName: string;
73
73
  documentationLink: string | null;
74
74
  parent: string | null;
75
- rootId: string;
76
75
  showInTimeline: boolean;
77
76
  nonce: NonceHistory;
78
77
  loopDisplay: LoopDisplay | undefined;
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import type { EffectsProp } from './effects/effect-types.js';
3
- import type { InteractiveBaseProps } from './Interactive.js';
3
+ import type { InteractiveBaseProps, InteractiveCropProps } from './Interactive.js';
4
4
  import type { AbsoluteFillLayout } from './Sequence.js';
5
5
  declare global {
6
6
  interface ElementImage {
@@ -54,7 +54,7 @@ export type HtmlInCanvasOnPaint = (params: HtmlInCanvasOnPaintParams) => void |
54
54
  export type HtmlInCanvasOnInitCleanup = () => void;
55
55
  export type HtmlInCanvasOnInit = (params: HtmlInCanvasOnPaintParams) => HtmlInCanvasOnInitCleanup | Promise<HtmlInCanvasOnInitCleanup>;
56
56
  export type HtmlInCanvasPixelDensity = number;
57
- export type HtmlInCanvasProps = Omit<InteractiveBaseProps, 'children'> & Omit<AbsoluteFillLayout, 'layout' | 'styleWhilePostmounted' | 'postmountFor' | 'premountFor' | 'styleWhilePremounted'> & {
57
+ export type HtmlInCanvasProps = Omit<InteractiveBaseProps, 'children'> & InteractiveCropProps & Omit<AbsoluteFillLayout, 'layout' | 'styleWhilePostmounted' | 'postmountFor' | 'premountFor' | 'styleWhilePremounted'> & {
58
58
  readonly durationInFrames?: number;
59
59
  readonly width: number;
60
60
  readonly height: number;
@@ -135,6 +135,46 @@ export declare const htmlInCanvasSchema: {
135
135
  readonly default: "transparent";
136
136
  readonly description: "Color";
137
137
  };
138
+ readonly cropLeft: {
139
+ readonly type: "number";
140
+ readonly default: 0;
141
+ readonly description: "Crop left";
142
+ readonly min: 0;
143
+ readonly max: 1;
144
+ readonly step: 0.01;
145
+ readonly hiddenFromList: false;
146
+ readonly keyframable: true;
147
+ };
148
+ readonly cropRight: {
149
+ readonly type: "number";
150
+ readonly default: 0;
151
+ readonly description: "Crop right";
152
+ readonly min: 0;
153
+ readonly max: 1;
154
+ readonly step: 0.01;
155
+ readonly hiddenFromList: false;
156
+ readonly keyframable: true;
157
+ };
158
+ readonly cropTop: {
159
+ readonly type: "number";
160
+ readonly default: 0;
161
+ readonly description: "Crop top";
162
+ readonly min: 0;
163
+ readonly max: 1;
164
+ readonly step: 0.01;
165
+ readonly hiddenFromList: false;
166
+ readonly keyframable: true;
167
+ };
168
+ readonly cropBottom: {
169
+ readonly type: "number";
170
+ readonly default: 0;
171
+ readonly description: "Crop bottom";
172
+ readonly min: 0;
173
+ readonly max: 1;
174
+ readonly step: 0.01;
175
+ readonly hiddenFromList: false;
176
+ readonly keyframable: true;
177
+ };
138
178
  readonly durationInFrames: {
139
179
  readonly type: "number";
140
180
  readonly default: undefined;
@@ -174,7 +214,7 @@ export declare const htmlInCanvasSchema: {
174
214
  readonly hiddenFromList: false;
175
215
  };
176
216
  };
177
- export declare const HtmlInCanvas: React.ForwardRefExoticComponent<Omit<InteractiveBaseProps, "children"> & Omit<AbsoluteFillLayout, "layout" | "postmountFor" | "premountFor" | "styleWhilePostmounted" | "styleWhilePremounted"> & {
217
+ export declare const HtmlInCanvas: React.ForwardRefExoticComponent<Omit<InteractiveBaseProps, "children"> & InteractiveCropProps & Omit<AbsoluteFillLayout, "layout" | "postmountFor" | "premountFor" | "styleWhilePostmounted" | "styleWhilePremounted"> & {
178
218
  readonly durationInFrames?: number | undefined;
179
219
  readonly width: number;
180
220
  readonly height: number;
@@ -9,6 +9,7 @@ const use_memoized_effects_js_1 = require("./effects/use-memoized-effects.js");
9
9
  const enable_sequence_stack_traces_js_1 = require("./enable-sequence-stack-traces.js");
10
10
  const interactivity_schema_js_1 = require("./interactivity-schema.js");
11
11
  const Sequence_js_1 = require("./Sequence.js");
12
+ const use_crop_style_js_1 = require("./use-crop-style.js");
12
13
  const use_delay_render_js_1 = require("./use-delay-render.js");
13
14
  const use_remotion_environment_js_1 = require("./use-remotion-environment.js");
14
15
  const with_interactivity_schema_js_1 = require("./with-interactivity-schema.js");
@@ -35,6 +36,17 @@ const isHtmlInCanvasSupported = () => {
35
36
  exports.isHtmlInCanvasSupported = isHtmlInCanvasSupported;
36
37
  /** Shown when {@link isHtmlInCanvasSupported} is false: APIs are absent (old Chrome and/or flag off). */
37
38
  exports.HTML_IN_CANVAS_UNSUPPORTED_MESSAGE = 'HTML in Canvas is not supported. Two common causes: Chrome is older than version 148 (update Chrome), or the HTML-in-Canvas flag is disabled at chrome://flags/#canvas-draw-element (enable it and restart Chrome).';
39
+ const MINIMUM_CHROME_VERSION_FOR_NESTED_HTML_IN_CANVAS = 152;
40
+ const getChromeMajorVersion = () => {
41
+ if (typeof navigator === 'undefined') {
42
+ return null;
43
+ }
44
+ const match = navigator.userAgent.match(/\b(?:HeadlessChrome|Chrome)\/(\d+)/);
45
+ if (!match) {
46
+ return null;
47
+ }
48
+ return Number(match[1]);
49
+ };
38
50
  function assertHtmlInCanvasDimensions(width, height) {
39
51
  if (typeof width !== 'number' || typeof height !== 'number') {
40
52
  throw new Error(`HtmlInCanvas: \`width\` and \`height\` must be numbers. Received width=${String(width)}, height=${String(height)}.`);
@@ -83,6 +95,12 @@ const HtmlInCanvasContent = (0, react_1.forwardRef)(({ width, height, effects, c
83
95
  var _a;
84
96
  const ancestor = (0, react_1.useContext)(HtmlInCanvasAncestorContext);
85
97
  assertHtmlInCanvasDimensions(width, height);
98
+ const chromeMajorVersion = getChromeMajorVersion();
99
+ if (ancestor &&
100
+ chromeMajorVersion !== null &&
101
+ chromeMajorVersion < MINIMUM_CHROME_VERSION_FOR_NESTED_HTML_IN_CANVAS) {
102
+ throw new Error(`Nested <HtmlInCanvas> components require Chrome ${MINIMUM_CHROME_VERSION_FOR_NESTED_HTML_IN_CANVAS} or newer, but the current browser is Chrome ${chromeMajorVersion}. Upgrade Chrome or avoid nesting components that use <HtmlInCanvas>, such as shapes with effects.`);
103
+ }
86
104
  const resolvedPixelDensity = resolveHtmlInCanvasPixelDensity(pixelDensity);
87
105
  const canvasWidth = Math.ceil(width * resolvedPixelDensity);
88
106
  const canvasHeight = Math.ceil(height * resolvedPixelDensity);
@@ -355,7 +373,7 @@ const HtmlInCanvasContent = (0, react_1.forwardRef)(({ width, height, effects, c
355
373
  return (jsx_runtime_1.jsx(HtmlInCanvasAncestorContext.Provider, { value: ancestorValue, children: jsx_runtime_1.jsx("canvas", { ref: setLayoutCanvasRef, width: canvasWidth, height: canvasHeight, style: canvasStyle, children: jsx_runtime_1.jsx("div", { ref: divRef, style: innerStyle, children: children }) }, canvasSizeKey) }));
356
374
  });
357
375
  HtmlInCanvasContent.displayName = 'HtmlInCanvasContent';
358
- const HtmlInCanvasInner = (0, react_1.forwardRef)(({ width, height, effects = [], children, onPaint, onInit, pixelDensity, controls, style, durationInFrames, name, ...sequenceProps }, ref) => {
376
+ const HtmlInCanvasInner = (0, react_1.forwardRef)(({ width, height, effects = [], children, onPaint, onInit, pixelDensity, controls, style, cropLeft, cropRight, cropTop, cropBottom, durationInFrames, name, ...sequenceProps }, ref) => {
359
377
  const memoizedEffectDefinitions = (0, use_memoized_effects_js_1.useMemoizedEffectDefinitions)(effects);
360
378
  const actualRef = (0, react_1.useRef)(null);
361
379
  const setCanvasRef = (0, react_1.useCallback)((node) => {
@@ -367,7 +385,15 @@ const HtmlInCanvasInner = (0, react_1.forwardRef)(({ width, height, effects = []
367
385
  ref.current = node;
368
386
  }
369
387
  }, [ref]);
370
- return (jsx_runtime_1.jsx(Sequence_js_1.Sequence, { durationInFrames: durationInFrames, name: name !== null && name !== void 0 ? name : '<HtmlInCanvas>', _remotionInternalDocumentationLink: "https://www.remotion.dev/docs/remotion/html-in-canvas", controls: controls, _remotionInternalEffects: memoizedEffectDefinitions, outlineRef: actualRef, layout: "none", ...sequenceProps, children: jsx_runtime_1.jsx(HtmlInCanvasContent, { ref: setCanvasRef, width: width, height: height, effects: effects, onPaint: onPaint, onInit: onInit, pixelDensity: pixelDensity, controls: controls, style: style, children: children }) }));
388
+ const croppedStyle = (0, use_crop_style_js_1.useCropStyle)({
389
+ cropLeft,
390
+ cropRight,
391
+ cropTop,
392
+ cropBottom,
393
+ style: style !== null && style !== void 0 ? style : null,
394
+ componentName: '<HtmlInCanvas />',
395
+ });
396
+ return (jsx_runtime_1.jsx(Sequence_js_1.Sequence, { durationInFrames: durationInFrames, name: name !== null && name !== void 0 ? name : '<HtmlInCanvas>', _remotionInternalDocumentationLink: "https://www.remotion.dev/docs/remotion/html-in-canvas", controls: controls, _remotionInternalEffects: memoizedEffectDefinitions, outlineRef: actualRef, layout: "none", ...sequenceProps, children: jsx_runtime_1.jsx(HtmlInCanvasContent, { ref: setCanvasRef, width: width, height: height, effects: effects, onPaint: onPaint, onInit: onInit, pixelDensity: pixelDensity, controls: controls, style: croppedStyle !== null && croppedStyle !== void 0 ? croppedStyle : undefined, children: children }) }));
371
397
  });
372
398
  HtmlInCanvasInner.displayName = 'HtmlInCanvas';
373
399
  exports.htmlInCanvasSchema = {
@@ -384,6 +410,7 @@ exports.htmlInCanvasSchema = {
384
410
  ...interactivity_schema_js_1.transformSchema,
385
411
  ...interactivity_schema_js_1.backgroundSchema,
386
412
  ...interactivity_schema_js_1.borderSchema,
413
+ ...interactivity_schema_js_1.cropSchema,
387
414
  };
388
415
  const HtmlInCanvasWrapped = (0, with_interactivity_schema_js_1.withInteractivitySchema)({
389
416
  Component: HtmlInCanvasInner,
package/dist/cjs/Img.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import type { EffectsProp } from './effects/effect-types.js';
3
- import type { InteractiveBaseProps, InteractivePremountProps } from './Interactive.js';
3
+ import type { InteractiveBaseProps, InteractiveCropProps, InteractivePremountProps } from './Interactive.js';
4
4
  type NativeImgProps = Omit<React.DetailedHTMLProps<React.ImgHTMLAttributes<HTMLImageElement>, HTMLImageElement>, 'src'>;
5
5
  export type ImgProps = NativeImgProps & {
6
6
  readonly maxRetries?: number;
@@ -16,7 +16,7 @@ export type ImgProps = NativeImgProps & {
16
16
  * @deprecated For internal use only
17
17
  */
18
18
  readonly stack?: string;
19
- } & InteractiveBaseProps & InteractivePremountProps;
19
+ } & InteractiveBaseProps & InteractiveCropProps & InteractivePremountProps;
20
20
  export declare const imgSchema: {
21
21
  readonly 'style.transformOrigin': {
22
22
  readonly type: "transform-origin";
@@ -105,6 +105,46 @@ export declare const imgSchema: {
105
105
  readonly hiddenFromList: true;
106
106
  readonly keyframable: false;
107
107
  };
108
+ readonly cropLeft: {
109
+ readonly type: "number";
110
+ readonly default: 0;
111
+ readonly description: "Crop left";
112
+ readonly min: 0;
113
+ readonly max: 1;
114
+ readonly step: 0.01;
115
+ readonly hiddenFromList: false;
116
+ readonly keyframable: true;
117
+ };
118
+ readonly cropRight: {
119
+ readonly type: "number";
120
+ readonly default: 0;
121
+ readonly description: "Crop right";
122
+ readonly min: 0;
123
+ readonly max: 1;
124
+ readonly step: 0.01;
125
+ readonly hiddenFromList: false;
126
+ readonly keyframable: true;
127
+ };
128
+ readonly cropTop: {
129
+ readonly type: "number";
130
+ readonly default: 0;
131
+ readonly description: "Crop top";
132
+ readonly min: 0;
133
+ readonly max: 1;
134
+ readonly step: 0.01;
135
+ readonly hiddenFromList: false;
136
+ readonly keyframable: true;
137
+ };
138
+ readonly cropBottom: {
139
+ readonly type: "number";
140
+ readonly default: 0;
141
+ readonly description: "Crop bottom";
142
+ readonly min: 0;
143
+ readonly max: 1;
144
+ readonly step: 0.01;
145
+ readonly hiddenFromList: false;
146
+ readonly keyframable: true;
147
+ };
108
148
  readonly durationInFrames: {
109
149
  readonly type: "number";
110
150
  readonly default: undefined;
@@ -155,5 +195,5 @@ export declare const Img: React.ComponentType<NativeImgProps & {
155
195
  * @deprecated For internal use only
156
196
  */
157
197
  readonly stack?: string | undefined;
158
- } & InteractiveBaseProps & InteractivePremountProps>;
198
+ } & InteractiveBaseProps & InteractiveCropProps & InteractivePremountProps>;
159
199
  export {};
package/dist/cjs/Img.js CHANGED
@@ -13,6 +13,7 @@ const Sequence_js_1 = require("./Sequence.js");
13
13
  const SequenceContext_js_1 = require("./SequenceContext.js");
14
14
  const truncate_src_for_label_js_1 = require("./truncate-src-for-label.js");
15
15
  const use_buffer_state_js_1 = require("./use-buffer-state.js");
16
+ const use_crop_style_js_1 = require("./use-crop-style.js");
16
17
  const use_delay_render_js_1 = require("./use-delay-render.js");
17
18
  const use_premounting_js_1 = require("./use-premounting.js");
18
19
  const use_remotion_environment_js_1 = require("./use-remotion-environment.js");
@@ -195,7 +196,7 @@ const ImgContent = ({ onError, maxRetries = 2, src, pauseWhenLoading, delayRende
195
196
  // blocks frame rendering.
196
197
  return (jsx_runtime_1.jsx("img", { ...props, ref: imageCallbackRef, crossOrigin: crossOriginValue, onError: didGetError, decoding: isRendering ? 'sync' : decoding }));
197
198
  };
198
- const NativeImgInner = ({ hidden, name, stack, showInTimeline, src, from, trimBefore, durationInFrames, freeze, premountFor, postmountFor, style, styleWhilePremounted, styleWhilePostmounted, controls, outlineRef: refForOutline, ...props }) => {
199
+ const NativeImgInner = ({ hidden, name, stack, showInTimeline, src, from, trimBefore, durationInFrames, freeze, premountFor, postmountFor, style, styleWhilePremounted, styleWhilePostmounted, cropLeft, cropRight, cropTop, cropBottom, controls, outlineRef: refForOutline, ...props }) => {
199
200
  if (!src) {
200
201
  throw new Error('No "src" prop was passed to <Img>.');
201
202
  }
@@ -209,7 +210,15 @@ const NativeImgInner = ({ hidden, name, stack, showInTimeline, src, from, trimBe
209
210
  styleWhilePostmounted: styleWhilePostmounted !== null && styleWhilePostmounted !== void 0 ? styleWhilePostmounted : null,
210
211
  hideWhilePremounted: 'display-none',
211
212
  });
212
- return (jsx_runtime_1.jsx(freeze_js_1.Freeze, { frame: freezeFrame, active: isPremountingOrPostmounting, children: jsx_runtime_1.jsx(Sequence_js_1.Sequence, { layout: "none", from: from !== null && from !== void 0 ? from : 0, trimBefore: trimBefore, durationInFrames: durationInFrames !== null && durationInFrames !== void 0 ? durationInFrames : Infinity, freeze: freeze, _remotionInternalStack: stack, _remotionInternalDocumentationLink: "https://www.remotion.dev/docs/img", _remotionInternalIsMedia: { type: 'image', src }, _remotionInternalPremountDisplay: effectivePremountFor || null, _remotionInternalPostmountDisplay: effectivePostmountFor || null, _remotionInternalIsPremounting: premountingActive, _remotionInternalIsPostmounting: postmountingActive, name: name !== null && name !== void 0 ? name : '<Img>', controls: controls, showInTimeline: showInTimeline !== null && showInTimeline !== void 0 ? showInTimeline : true, hidden: hidden, outlineRef: refForOutline, children: jsx_runtime_1.jsx(ImgContent, { src: src, refForOutline: refForOutline, style: premountingStyle !== null && premountingStyle !== void 0 ? premountingStyle : undefined, ...props }) }) }));
213
+ const croppedStyle = (0, use_crop_style_js_1.useCropStyle)({
214
+ cropLeft,
215
+ cropRight,
216
+ cropTop,
217
+ cropBottom,
218
+ style: premountingStyle,
219
+ componentName: '<Img />',
220
+ });
221
+ return (jsx_runtime_1.jsx(freeze_js_1.Freeze, { frame: freezeFrame, active: isPremountingOrPostmounting, children: jsx_runtime_1.jsx(Sequence_js_1.Sequence, { layout: "none", from: from !== null && from !== void 0 ? from : 0, trimBefore: trimBefore, durationInFrames: durationInFrames !== null && durationInFrames !== void 0 ? durationInFrames : Infinity, freeze: freeze, _remotionInternalStack: stack, _remotionInternalDocumentationLink: "https://www.remotion.dev/docs/img", _remotionInternalIsMedia: { type: 'image', src }, _remotionInternalPremountDisplay: effectivePremountFor || null, _remotionInternalPostmountDisplay: effectivePostmountFor || null, _remotionInternalIsPremounting: premountingActive, _remotionInternalIsPostmounting: postmountingActive, name: name !== null && name !== void 0 ? name : '<Img>', controls: controls, showInTimeline: showInTimeline !== null && showInTimeline !== void 0 ? showInTimeline : true, hidden: hidden, outlineRef: refForOutline, children: jsx_runtime_1.jsx(ImgContent, { src: src, refForOutline: refForOutline, style: croppedStyle !== null && croppedStyle !== void 0 ? croppedStyle : undefined, ...props }) }) }));
213
222
  };
214
223
  const CanvasImageWithPrivateProps = index_js_1.CanvasImage;
215
224
  exports.imgSchema = {
@@ -220,6 +229,7 @@ exports.imgSchema = {
220
229
  keyframable: false,
221
230
  },
222
231
  ...interactivity_schema_js_1.baseSchema,
232
+ ...interactivity_schema_js_1.cropSchema,
223
233
  ...interactivity_schema_js_1.premountSchema,
224
234
  ...interactivity_schema_js_1.transformSchema,
225
235
  ...interactivity_schema_js_1.backgroundSchema,
@@ -264,12 +274,12 @@ const getFitFromObjectFit = (style) => {
264
274
  }
265
275
  return undefined;
266
276
  };
267
- const ImgInner = ({ effects = [], ref, hidden, name, stack, showInTimeline, src, from, trimBefore, durationInFrames, freeze, premountFor, postmountFor, styleWhilePremounted, styleWhilePostmounted, controls, width, height, className, style, id, pauseWhenLoading, maxRetries, delayRenderRetries, delayRenderTimeoutInMilliseconds, ...props }) => {
277
+ const ImgInner = ({ effects = [], ref, hidden, name, stack, showInTimeline, src, from, trimBefore, durationInFrames, freeze, premountFor, postmountFor, styleWhilePremounted, styleWhilePostmounted, controls, width, height, className, style, cropLeft, cropRight, cropTop, cropBottom, id, pauseWhenLoading, maxRetries, delayRenderRetries, delayRenderTimeoutInMilliseconds, ...props }) => {
268
278
  var _a;
269
279
  const refForOutline = (0, react_1.useRef)(null);
270
280
  const shouldPauseWhenLoading = (0, v5_flag_js_1.resolveV5Default)(pauseWhenLoading);
271
281
  if (effects.length === 0) {
272
- return (jsx_runtime_1.jsx(NativeImgInner, { ...props, ref: ref, hidden: hidden, name: name, stack: stack, showInTimeline: showInTimeline, src: src, from: from, trimBefore: trimBefore, durationInFrames: durationInFrames, freeze: freeze, premountFor: premountFor, postmountFor: postmountFor, styleWhilePremounted: styleWhilePremounted, styleWhilePostmounted: styleWhilePostmounted, controls: controls, width: width, height: height, className: className, style: style, id: id, pauseWhenLoading: shouldPauseWhenLoading, maxRetries: maxRetries, delayRenderRetries: delayRenderRetries, delayRenderTimeoutInMilliseconds: delayRenderTimeoutInMilliseconds, outlineRef: refForOutline }));
282
+ return (jsx_runtime_1.jsx(NativeImgInner, { ...props, ref: ref, hidden: hidden, name: name, stack: stack, showInTimeline: showInTimeline, src: src, from: from, trimBefore: trimBefore, durationInFrames: durationInFrames, freeze: freeze, premountFor: premountFor, postmountFor: postmountFor, styleWhilePremounted: styleWhilePremounted, styleWhilePostmounted: styleWhilePostmounted, controls: controls, width: width, height: height, className: className, style: style, cropLeft: cropLeft, cropRight: cropRight, cropTop: cropTop, cropBottom: cropBottom, id: id, pauseWhenLoading: shouldPauseWhenLoading, maxRetries: maxRetries, delayRenderRetries: delayRenderRetries, delayRenderTimeoutInMilliseconds: delayRenderTimeoutInMilliseconds, outlineRef: refForOutline }));
273
283
  }
274
284
  if (!src) {
275
285
  throw new Error('No "src" prop was passed to <Img>.');
@@ -284,7 +294,7 @@ const ImgInner = ({ effects = [], ref, hidden, name, stack, showInTimeline, src,
284
294
  const canvasHeight = typeof height === 'number' ? height : undefined;
285
295
  const canvasProps = props;
286
296
  const canvasFit = (_a = getFitFromObjectFit(style)) !== null && _a !== void 0 ? _a : 'fill';
287
- return (jsx_runtime_1.jsx(CanvasImageWithPrivateProps, { src: src, width: canvasWidth, height: canvasHeight, fit: canvasFit, effects: effects, className: className, style: style, id: id, pauseWhenLoading: shouldPauseWhenLoading, maxRetries: maxRetries, delayRenderRetries: delayRenderRetries, delayRenderTimeoutInMilliseconds: delayRenderTimeoutInMilliseconds, from: from, trimBefore: trimBefore, durationInFrames: durationInFrames, freeze: freeze, premountFor: premountFor, postmountFor: postmountFor, styleWhilePremounted: styleWhilePremounted, styleWhilePostmounted: styleWhilePostmounted, hidden: hidden, name: name !== null && name !== void 0 ? name : '<Img>', showInTimeline: showInTimeline, stack: stack, _remotionInternalDocumentationLink: "https://www.remotion.dev/docs/img", controls: controls, outlineRef: refForOutline, ...canvasProps }));
297
+ return (jsx_runtime_1.jsx(CanvasImageWithPrivateProps, { src: src, width: canvasWidth, height: canvasHeight, fit: canvasFit, effects: effects, className: className, style: style, cropLeft: cropLeft, cropRight: cropRight, cropTop: cropTop, cropBottom: cropBottom, id: id, pauseWhenLoading: shouldPauseWhenLoading, maxRetries: maxRetries, delayRenderRetries: delayRenderRetries, delayRenderTimeoutInMilliseconds: delayRenderTimeoutInMilliseconds, from: from, trimBefore: trimBefore, durationInFrames: durationInFrames, freeze: freeze, premountFor: premountFor, postmountFor: postmountFor, styleWhilePremounted: styleWhilePremounted, styleWhilePostmounted: styleWhilePostmounted, hidden: hidden, name: name !== null && name !== void 0 ? name : '<Img>', showInTimeline: showInTimeline, stack: stack, _remotionInternalDocumentationLink: "https://www.remotion.dev/docs/img", _remotionInternalCropComponentName: "<Img />", controls: controls, outlineRef: refForOutline, ...canvasProps }));
288
298
  };
289
299
  /*
290
300
  * @description Works just like a regular HTML img tag. When you use the <Img> tag, Remotion will ensure that the image is loaded before rendering the frame.
@@ -8,6 +8,7 @@ type InteractiveTag = InteractiveHtmlTag | InteractiveSvgTag;
8
8
  type ElementForTag<Tag extends InteractiveTag> = Tag extends keyof HTMLElementTagNameMap ? HTMLElementTagNameMap[Tag] : Tag extends keyof SVGElementTagNameMap ? SVGElementTagNameMap[Tag] : Element;
9
9
  export type InteractiveBaseProps = Pick<SequenceProps, 'durationInFrames' | 'from' | 'trimBefore' | 'freeze' | 'hidden' | 'name' | 'showInTimeline'>;
10
10
  export type InteractiveTransformProps = Pick<AbsoluteFillLayout, 'style'>;
11
+ export type InteractiveCropProps = Pick<SequenceProps, 'cropLeft' | 'cropRight' | 'cropTop' | 'cropBottom'>;
11
12
  export type InteractivePremountProps = Pick<AbsoluteFillLayout, 'premountFor' | 'postmountFor' | 'styleWhilePremounted' | 'styleWhilePostmounted'>;
12
13
  type InteractiveSequenceProps = InteractiveBaseProps & {
13
14
  /**
@@ -206,6 +207,83 @@ export declare const Interactive: {
206
207
  readonly description: "Border color";
207
208
  };
208
209
  };
210
+ cropSchema: {
211
+ readonly cropLeft: {
212
+ readonly type: "number";
213
+ readonly default: 0;
214
+ readonly description: "Crop left";
215
+ readonly min: 0;
216
+ readonly max: 1;
217
+ readonly step: 0.01;
218
+ readonly hiddenFromList: false;
219
+ readonly keyframable: true;
220
+ };
221
+ readonly cropRight: {
222
+ readonly type: "number";
223
+ readonly default: 0;
224
+ readonly description: "Crop right";
225
+ readonly min: 0;
226
+ readonly max: 1;
227
+ readonly step: 0.01;
228
+ readonly hiddenFromList: false;
229
+ readonly keyframable: true;
230
+ };
231
+ readonly cropTop: {
232
+ readonly type: "number";
233
+ readonly default: 0;
234
+ readonly description: "Crop top";
235
+ readonly min: 0;
236
+ readonly max: 1;
237
+ readonly step: 0.01;
238
+ readonly hiddenFromList: false;
239
+ readonly keyframable: true;
240
+ };
241
+ readonly cropBottom: {
242
+ readonly type: "number";
243
+ readonly default: 0;
244
+ readonly description: "Crop bottom";
245
+ readonly min: 0;
246
+ readonly max: 1;
247
+ readonly step: 0.01;
248
+ readonly hiddenFromList: false;
249
+ readonly keyframable: true;
250
+ };
251
+ };
252
+ svgPaintSchema: {
253
+ readonly stroke: {
254
+ readonly type: "color";
255
+ readonly default: "none";
256
+ readonly description: "Stroke";
257
+ };
258
+ readonly strokeWidth: {
259
+ readonly type: "number";
260
+ readonly default: 1;
261
+ readonly description: "Stroke width";
262
+ readonly min: 0;
263
+ readonly step: 1;
264
+ readonly hiddenFromList: false;
265
+ };
266
+ readonly fill: {
267
+ readonly type: "color";
268
+ readonly default: undefined;
269
+ readonly description: "Fill";
270
+ };
271
+ };
272
+ svgStrokeSchema: {
273
+ readonly stroke: {
274
+ readonly type: "color";
275
+ readonly default: "none";
276
+ readonly description: "Stroke";
277
+ };
278
+ readonly strokeWidth: {
279
+ readonly type: "number";
280
+ readonly default: 1;
281
+ readonly description: "Stroke width";
282
+ readonly min: 0;
283
+ readonly step: 1;
284
+ readonly hiddenFromList: false;
285
+ };
286
+ };
209
287
  premountSchema: {
210
288
  readonly premountFor: {
211
289
  readonly type: "number";
@@ -348,6 +426,46 @@ export declare const Interactive: {
348
426
  readonly hiddenFromList: true;
349
427
  readonly keyframable: false;
350
428
  };
429
+ readonly cropLeft: {
430
+ readonly type: "number";
431
+ readonly default: 0;
432
+ readonly description: "Crop left";
433
+ readonly min: 0;
434
+ readonly max: 1;
435
+ readonly step: 0.01;
436
+ readonly hiddenFromList: false;
437
+ readonly keyframable: true;
438
+ };
439
+ readonly cropRight: {
440
+ readonly type: "number";
441
+ readonly default: 0;
442
+ readonly description: "Crop right";
443
+ readonly min: 0;
444
+ readonly max: 1;
445
+ readonly step: 0.01;
446
+ readonly hiddenFromList: false;
447
+ readonly keyframable: true;
448
+ };
449
+ readonly cropTop: {
450
+ readonly type: "number";
451
+ readonly default: 0;
452
+ readonly description: "Crop top";
453
+ readonly min: 0;
454
+ readonly max: 1;
455
+ readonly step: 0.01;
456
+ readonly hiddenFromList: false;
457
+ readonly keyframable: true;
458
+ };
459
+ readonly cropBottom: {
460
+ readonly type: "number";
461
+ readonly default: 0;
462
+ readonly description: "Crop bottom";
463
+ readonly min: 0;
464
+ readonly max: 1;
465
+ readonly step: 0.01;
466
+ readonly hiddenFromList: false;
467
+ readonly keyframable: true;
468
+ };
351
469
  };
352
470
  readonly none: {};
353
471
  };
@@ -74,9 +74,22 @@ const interactiveTextElementSchema = {
74
74
  };
75
75
  const interactiveSvgTextElementSchema = {
76
76
  ...interactiveElementSchema,
77
+ ...interactivity_schema_js_1.svgPaintSchema,
77
78
  ...interactivity_schema_js_1.textSchema,
78
79
  ...interactivity_schema_js_1.textContentSchema,
79
80
  };
81
+ const interactiveSvgElementSchema = {
82
+ ...interactiveElementSchema,
83
+ ...interactivity_schema_js_1.svgPaintSchema,
84
+ };
85
+ const interactiveSvgStrokeElementSchema = {
86
+ ...interactiveElementSchema,
87
+ ...interactivity_schema_js_1.svgStrokeSchema,
88
+ };
89
+ const interactiveSvgRootElementSchema = {
90
+ ...interactiveBorderElementSchema,
91
+ ...interactivity_schema_js_1.svgPaintSchema,
92
+ };
80
93
  const setRef = (ref, value) => {
81
94
  if (typeof ref === 'function') {
82
95
  ref(value);
@@ -120,8 +133,11 @@ const makeInteractiveElement = (tag, displayName, schema) => {
120
133
  const makeInteractiveTextElement = (tag, displayName) => {
121
134
  return makeInteractiveElement(tag, displayName, interactiveTextElementSchema);
122
135
  };
123
- const makeInteractiveNonTextElement = (tag, displayName) => {
124
- return makeInteractiveElement(tag, displayName, interactiveElementSchema);
136
+ const makeInteractiveSvgElement = (tag, displayName) => {
137
+ return makeInteractiveElement(tag, displayName, interactiveSvgElementSchema);
138
+ };
139
+ const makeInteractiveSvgStrokeElement = (tag, displayName) => {
140
+ return makeInteractiveElement(tag, displayName, interactiveSvgStrokeElementSchema);
125
141
  };
126
142
  /**
127
143
  * @description HTML and SVG elements that are registered in the Remotion Studio timeline and can be visually edited.
@@ -132,6 +148,9 @@ exports.Interactive = {
132
148
  textSchema: interactivity_schema_js_1.textSchema,
133
149
  backgroundSchema: interactivity_schema_js_1.backgroundSchema,
134
150
  borderSchema: interactivity_schema_js_1.borderSchema,
151
+ cropSchema: interactivity_schema_js_1.cropSchema,
152
+ svgPaintSchema: interactivity_schema_js_1.svgPaintSchema,
153
+ svgStrokeSchema: interactivity_schema_js_1.svgStrokeSchema,
135
154
  premountSchema: interactivity_schema_js_1.premountSchema,
136
155
  sequenceSchema: interactivity_schema_js_1.sequenceSchema,
137
156
  withSchema,
@@ -140,13 +159,13 @@ exports.Interactive = {
140
159
  Article: makeInteractiveTextElement('article', '<Interactive.Article>'),
141
160
  Aside: makeInteractiveTextElement('aside', '<Interactive.Aside>'),
142
161
  Button: makeInteractiveTextElement('button', '<Interactive.Button>'),
143
- Circle: makeInteractiveNonTextElement('circle', '<Interactive.Circle>'),
162
+ Circle: makeInteractiveSvgElement('circle', '<Interactive.Circle>'),
144
163
  Code: makeInteractiveTextElement('code', '<Interactive.Code>'),
145
164
  Div: makeInteractiveTextElement('div', '<Interactive.Div>'),
146
- Ellipse: makeInteractiveNonTextElement('ellipse', '<Interactive.Ellipse>'),
165
+ Ellipse: makeInteractiveSvgElement('ellipse', '<Interactive.Ellipse>'),
147
166
  Em: makeInteractiveTextElement('em', '<Interactive.Em>'),
148
167
  Footer: makeInteractiveTextElement('footer', '<Interactive.Footer>'),
149
- G: makeInteractiveNonTextElement('g', '<Interactive.G>'),
168
+ G: makeInteractiveSvgElement('g', '<Interactive.G>'),
150
169
  H1: makeInteractiveTextElement('h1', '<Interactive.H1>'),
151
170
  H2: makeInteractiveTextElement('h2', '<Interactive.H2>'),
152
171
  H3: makeInteractiveTextElement('h3', '<Interactive.H3>'),
@@ -156,19 +175,19 @@ exports.Interactive = {
156
175
  Header: makeInteractiveTextElement('header', '<Interactive.Header>'),
157
176
  Label: makeInteractiveTextElement('label', '<Interactive.Label>'),
158
177
  Li: makeInteractiveTextElement('li', '<Interactive.Li>'),
159
- Line: makeInteractiveNonTextElement('line', '<Interactive.Line>'),
178
+ Line: makeInteractiveSvgStrokeElement('line', '<Interactive.Line>'),
160
179
  Main: makeInteractiveTextElement('main', '<Interactive.Main>'),
161
180
  Nav: makeInteractiveTextElement('nav', '<Interactive.Nav>'),
162
181
  Ol: makeInteractiveTextElement('ol', '<Interactive.Ol>'),
163
182
  P: makeInteractiveTextElement('p', '<Interactive.P>'),
164
- Path: makeInteractiveNonTextElement('path', '<Interactive.Path>'),
183
+ Path: makeInteractiveSvgElement('path', '<Interactive.Path>'),
165
184
  Pre: makeInteractiveTextElement('pre', '<Interactive.Pre>'),
166
- Rect: makeInteractiveNonTextElement('rect', '<Interactive.Rect>'),
185
+ Rect: makeInteractiveSvgElement('rect', '<Interactive.Rect>'),
167
186
  Section: makeInteractiveTextElement('section', '<Interactive.Section>'),
168
187
  Small: makeInteractiveTextElement('small', '<Interactive.Small>'),
169
188
  Span: makeInteractiveTextElement('span', '<Interactive.Span>'),
170
189
  Strong: makeInteractiveTextElement('strong', '<Interactive.Strong>'),
171
- Svg: makeInteractiveElement('svg', '<Interactive.Svg>', interactiveBorderElementSchema),
190
+ Svg: makeInteractiveElement('svg', '<Interactive.Svg>', interactiveSvgRootElementSchema),
172
191
  Text: makeInteractiveElement('text', '<Interactive.Text>', interactiveSvgTextElementSchema),
173
192
  Ul: makeInteractiveTextElement('ul', '<Interactive.Ul>'),
174
193
  };
@@ -18,6 +18,10 @@ export type SequencePropsWithoutDuration = {
18
18
  readonly children?: React.ReactNode;
19
19
  readonly width?: number;
20
20
  readonly height?: number;
21
+ readonly cropLeft?: number;
22
+ readonly cropRight?: number;
23
+ readonly cropTop?: number;
24
+ readonly cropBottom?: number;
21
25
  readonly from?: number;
22
26
  readonly trimBefore?: number;
23
27
  readonly freeze?: number | null;
@@ -8,6 +8,7 @@ const AbsoluteFill_js_1 = require("./AbsoluteFill.js");
8
8
  const freeze_js_1 = require("./freeze.js");
9
9
  const interactivity_schema_js_1 = require("./interactivity-schema.js");
10
10
  const nonce_js_1 = require("./nonce.js");
11
+ const sequence_crop_js_1 = require("./sequence-crop.js");
11
12
  const SequenceContext_js_1 = require("./SequenceContext.js");
12
13
  const SequenceManager_js_1 = require("./SequenceManager.js");
13
14
  const is_inside_series_js_1 = require("./series/is-inside-series.js");
@@ -18,12 +19,11 @@ const use_video_config_js_1 = require("./use-video-config.js");
18
19
  const v5_flag_js_1 = require("./v5-flag.js");
19
20
  const with_interactivity_schema_js_1 = require("./with-interactivity-schema.js");
20
21
  const EMPTY_EFFECTS = [];
21
- const RegularSequenceRefForwardingFunction = ({ from = 0, trimBefore = 0, freeze, durationInFrames = Infinity, children, name, height, width, showInTimeline = true, hidden = false, controls, _remotionInternalEffects, _remotionInternalLoopDisplay: loopDisplay, _remotionInternalStack: stack, _remotionInternalDocumentationLink: documentationLink, _remotionInternalSingleChildComponent: singleChildComponent, _remotionInternalPremountDisplay: premountDisplay, _remotionInternalPostmountDisplay: postmountDisplay, _remotionInternalIsMedia: isMedia, outlineRef: passedRefForOutline, ...other }, ref) => {
22
+ const RegularSequenceRefForwardingFunction = ({ from = 0, trimBefore = 0, freeze, durationInFrames = Infinity, children, name, height, width, showInTimeline = true, hidden = false, controls, _remotionInternalEffects, _remotionInternalLoopDisplay: loopDisplay, _remotionInternalStack: stack, _remotionInternalDocumentationLink: documentationLink, _remotionInternalSingleChildComponent: singleChildComponent, _remotionInternalPremountDisplay: premountDisplay, _remotionInternalPostmountDisplay: postmountDisplay, _remotionInternalIsMedia: isMedia, outlineRef: passedRefForOutline, cropLeft, cropRight, cropTop, cropBottom, ...other }, ref) => {
22
23
  var _a, _b, _c;
23
24
  const { layout = 'absolute-fill' } = other;
24
25
  const [id] = (0, react_1.useState)(() => String(Math.random()));
25
26
  const parentSequence = (0, react_1.useContext)(SequenceContext_js_1.SequenceContext);
26
- const { rootId } = (0, timeline_position_state_js_1.useTimelineContext)();
27
27
  const cumulatedFrom = parentSequence
28
28
  ? parentSequence.cumulatedFrom + parentSequence.relativeFrom
29
29
  : 0;
@@ -31,6 +31,13 @@ const RegularSequenceRefForwardingFunction = ({ from = 0, trimBefore = 0, freeze
31
31
  if (layout !== 'absolute-fill' && layout !== 'none') {
32
32
  throw new TypeError(`The layout prop of <Sequence /> expects either "absolute-fill" or "none", but you passed: ${layout}`);
33
33
  }
34
+ const cropProps = { cropLeft, cropRight, cropTop, cropBottom };
35
+ const hasCropProp = Object.values(cropProps).some((value) => value !== undefined);
36
+ if (layout === 'none' && hasCropProp) {
37
+ throw new TypeError('The cropLeft, cropRight, cropTop and cropBottom props of <Sequence /> are only supported with layout="absolute-fill".');
38
+ }
39
+ (0, sequence_crop_js_1.validateSequenceCrop)(cropProps);
40
+ const { left: resolvedCropLeft, right: resolvedCropRight, top: resolvedCropTop, bottom: resolvedCropBottom, } = (0, sequence_crop_js_1.resolveSequenceCrop)(cropProps);
34
41
  // @ts-expect-error
35
42
  if (layout === 'none' && typeof other.style !== 'undefined') {
36
43
  throw new TypeError('If layout="none", you may not pass a style. Passed: ' +
@@ -202,7 +209,6 @@ const RegularSequenceRefForwardingFunction = ({ from = 0, trimBefore = 0, freeze
202
209
  parent: (_a = parentSequence === null || parentSequence === void 0 ? void 0 : parentSequence.id) !== null && _a !== void 0 ? _a : null,
203
210
  postmountDisplay: postmountDisplay !== null && postmountDisplay !== void 0 ? postmountDisplay : null,
204
211
  premountDisplay: premountDisplay !== null && premountDisplay !== void 0 ? premountDisplay : null,
205
- rootId,
206
212
  showInTimeline,
207
213
  src: isMedia.src,
208
214
  getStack: () => stackRef.current,
@@ -230,7 +236,6 @@ const RegularSequenceRefForwardingFunction = ({ from = 0, trimBefore = 0, freeze
230
236
  playbackRate: isMedia.data.playbackRate,
231
237
  postmountDisplay: postmountDisplay !== null && postmountDisplay !== void 0 ? postmountDisplay : null,
232
238
  premountDisplay: premountDisplay !== null && premountDisplay !== void 0 ? premountDisplay : null,
233
- rootId,
234
239
  showInTimeline,
235
240
  src: isMedia.data.src,
236
241
  getStack: () => stackRef.current,
@@ -257,7 +262,6 @@ const RegularSequenceRefForwardingFunction = ({ from = 0, trimBefore = 0, freeze
257
262
  documentationLink: resolvedDocumentationLink,
258
263
  parent: (_c = parentSequence === null || parentSequence === void 0 ? void 0 : parentSequence.id) !== null && _c !== void 0 ? _c : null,
259
264
  type: 'sequence',
260
- rootId,
261
265
  showInTimeline,
262
266
  nonce: nonce.get(),
263
267
  loopDisplay,
@@ -283,7 +287,6 @@ const RegularSequenceRefForwardingFunction = ({ from = 0, trimBefore = 0, freeze
283
287
  unregisterSequence,
284
288
  parentSequence === null || parentSequence === void 0 ? void 0 : parentSequence.id,
285
289
  actualDurationInFrames,
286
- rootId,
287
290
  from,
288
291
  trimBefore,
289
292
  registeredTrimBefore,
@@ -315,6 +318,13 @@ const RegularSequenceRefForwardingFunction = ({ from = 0, trimBefore = 0, freeze
315
318
  : children;
316
319
  const frozenContent = content === null || typeof freeze === 'undefined' || freeze === null ? (content) : (jsx_runtime_1.jsx(freeze_js_1.Freeze, { frame: freeze, children: content }));
317
320
  const styleIfThere = other.layout === 'none' ? undefined : other.style;
321
+ const cropClipPath = (0, sequence_crop_js_1.getSequenceCropClipPath)({
322
+ left: resolvedCropLeft,
323
+ right: resolvedCropRight,
324
+ top: resolvedCropTop,
325
+ bottom: resolvedCropBottom,
326
+ borderRadius: styleIfThere === null || styleIfThere === void 0 ? void 0 : styleIfThere.borderRadius,
327
+ });
318
328
  const sequenceRef = (0, react_1.useCallback)((node) => {
319
329
  wrapperRefForOutline.current = node;
320
330
  if (typeof ref === 'function') {
@@ -330,8 +340,13 @@ const RegularSequenceRefForwardingFunction = ({ from = 0, trimBefore = 0, freeze
330
340
  ...(width ? { width } : {}),
331
341
  ...(height ? { height } : {}),
332
342
  ...(styleIfThere !== null && styleIfThere !== void 0 ? styleIfThere : {}),
343
+ ...(cropClipPath
344
+ ? {
345
+ clipPath: cropClipPath,
346
+ }
347
+ : {}),
333
348
  };
334
- }, [height, styleIfThere, width]);
349
+ }, [cropClipPath, height, styleIfThere, width]);
335
350
  if (ref !== null && layout === 'none') {
336
351
  throw new TypeError('It is not supported to pass both a `ref` and `layout="none"` to <Sequence />.');
337
352
  }
@@ -4,7 +4,6 @@ import { type PlayableMediaTag } from './timeline-position-state';
4
4
  export type TimelineContextValue = {
5
5
  frame: Record<string, number>;
6
6
  playing: boolean;
7
- rootId: string;
8
7
  imperativePlaying: RefObject<boolean>;
9
8
  audioAndVideoTags: RefObject<PlayableMediaTag[]>;
10
9
  };