@remotion/studio 4.0.496 → 4.0.497

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 (81) hide show
  1. package/dist/components/AudioWaveform.js +1 -11
  2. package/dist/components/Canvas.js +22 -203
  3. package/dist/components/CompositionSelectorItem.js +2 -10
  4. package/dist/components/InspectorPanel/AlignmentControls.js +2 -0
  5. package/dist/components/InspectorPanel/ConnectedCompositionsSection.js +27 -2
  6. package/dist/components/InspectorPanel/SequenceSelectionInspector.js +65 -8
  7. package/dist/components/InspectorPanel/use-composition-actions.js +6 -2
  8. package/dist/components/NewComposition/CodemodFooter.d.ts +1 -1
  9. package/dist/components/NewComposition/CodemodFooter.js +23 -4
  10. package/dist/components/NewComposition/InputDragger.d.ts +6 -0
  11. package/dist/components/NewComposition/InputDragger.js +12 -3
  12. package/dist/components/NewComposition/NewComposition.js +1 -1
  13. package/dist/components/NewComposition/use-rename-static-file.js +1 -1
  14. package/dist/components/SelectedOutlineElement.js +56 -88
  15. package/dist/components/SelectedOutlineOverlay.d.ts +1 -1
  16. package/dist/components/SelectedOutlineOverlay.js +9 -10
  17. package/dist/components/Timeline/Timeline.js +10 -3
  18. package/dist/components/Timeline/TimelineAssetDropIndicator.d.ts +2 -0
  19. package/dist/components/Timeline/TimelineAssetDropIndicator.js +37 -0
  20. package/dist/components/Timeline/TimelineClipboardKeybindings.js +1 -7
  21. package/dist/components/Timeline/TimelineScrollable.js +3 -2
  22. package/dist/components/Timeline/TimelineSelection.d.ts +4 -0
  23. package/dist/components/Timeline/TimelineSelection.js +40 -5
  24. package/dist/components/Timeline/TimelineSequence.js +20 -8
  25. package/dist/components/Timeline/TimelineSequenceFrame.js +2 -4
  26. package/dist/components/Timeline/TimelineSequenceItem.js +2 -0
  27. package/dist/components/Timeline/TimelineSequencePropItem.js +4 -0
  28. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.d.ts +15 -3
  29. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +96 -18
  30. package/dist/components/Timeline/TimelineTimeIndicators.d.ts +16 -0
  31. package/dist/components/Timeline/TimelineTimeIndicators.js +154 -35
  32. package/dist/components/Timeline/TimelineTranslateField.js +2 -1
  33. package/dist/components/Timeline/TimelineVideoInfo.d.ts +1 -0
  34. package/dist/components/Timeline/TimelineVideoInfo.js +4 -1
  35. package/dist/components/Timeline/delete-selected-timeline-item.d.ts +2 -0
  36. package/dist/components/Timeline/delete-selected-timeline-item.js +5 -4
  37. package/dist/components/Timeline/disable-sequence-interactivity.js +2 -0
  38. package/dist/components/Timeline/get-timeline-media-visualization-layout.d.ts +8 -0
  39. package/dist/components/Timeline/get-timeline-media-visualization-layout.js +10 -0
  40. package/dist/components/Timeline/get-timeline-video-info-widths.js +11 -3
  41. package/dist/components/Timeline/keyframe-clipboard.js +21 -5
  42. package/dist/components/Timeline/reset-selected-timeline-props.js +2 -0
  43. package/dist/components/Timeline/save-sequence-prop.d.ts +5 -3
  44. package/dist/components/Timeline/save-sequence-prop.js +43 -18
  45. package/dist/components/Timeline/should-clear-selection-on-pointer-down.d.ts +2 -0
  46. package/dist/components/Timeline/should-clear-selection-on-pointer-down.js +1 -1
  47. package/dist/components/Timeline/timeline-asset-drop-context.d.ts +1 -0
  48. package/dist/components/Timeline/timeline-asset-drop-context.js +5 -0
  49. package/dist/components/Timeline/timeline-scroll-logic.d.ts +7 -0
  50. package/dist/components/Timeline/timeline-scroll-logic.js +10 -1
  51. package/dist/components/Timeline/use-rename-sequence.js +2 -0
  52. package/dist/components/Timeline/use-sequence-freeze-frame-menu-item.js +2 -0
  53. package/dist/components/Timeline/use-timeline-asset-drop.d.ts +1 -0
  54. package/dist/components/Timeline/use-timeline-asset-drop.js +168 -0
  55. package/dist/components/composition-menu-items.d.ts +15 -1
  56. package/dist/components/composition-menu-items.js +137 -107
  57. package/dist/components/drop-handler-data.d.ts +13 -0
  58. package/dist/components/drop-handler-data.js +117 -0
  59. package/dist/components/handle-drop.d.ts +13 -0
  60. package/dist/components/handle-drop.js +115 -0
  61. package/dist/components/import-assets.d.ts +26 -8
  62. package/dist/components/import-assets.js +161 -49
  63. package/dist/components/selected-outline-drag.d.ts +11 -1
  64. package/dist/components/selected-outline-drag.js +74 -1
  65. package/dist/esm/{chunk-0v4n7nkh.js → chunk-5wj95bdd.js} +4262 -3392
  66. package/dist/esm/internals.mjs +4262 -3392
  67. package/dist/esm/previewEntry.mjs +4464 -3594
  68. package/dist/esm/renderEntry.mjs +1 -1
  69. package/dist/helpers/is-video-with-last-frame-hold.d.ts +2 -0
  70. package/dist/helpers/is-video-with-last-frame-hold.js +9 -0
  71. package/dist/helpers/url-state.d.ts +1 -0
  72. package/dist/helpers/url-state.js +5 -1
  73. package/dist/helpers/use-max-media-duration.js +5 -3
  74. package/dist/helpers/use-menu-structure.js +2 -0
  75. package/dist/icons/duplicate.d.ts +5 -0
  76. package/dist/icons/duplicate.js +10 -0
  77. package/dist/icons/snowflake.d.ts +5 -0
  78. package/dist/icons/snowflake.js +10 -0
  79. package/dist/icons/trash.d.ts +5 -0
  80. package/dist/icons/trash.js +8 -0
  81. package/package.json +11 -11
@@ -43,6 +43,7 @@ const format_file_location_1 = require("../../helpers/format-file-location");
43
43
  const get_sequence_double_click_action_1 = require("../../helpers/get-sequence-double-click-action");
44
44
  const get_timeline_sequence_layout_1 = require("../../helpers/get-timeline-sequence-layout");
45
45
  const interactivity_enabled_1 = require("../../helpers/interactivity-enabled");
46
+ const is_video_with_last_frame_hold_1 = require("../../helpers/is-video-with-last-frame-hold");
46
47
  const open_in_editor_1 = require("../../helpers/open-in-editor");
47
48
  const timeline_layout_1 = require("../../helpers/timeline-layout");
48
49
  const use_max_media_duration_1 = require("../../helpers/use-max-media-duration");
@@ -56,6 +57,7 @@ const use_select_asset_1 = require("../use-select-asset");
56
57
  const disable_sequence_interactivity_1 = require("./disable-sequence-interactivity");
57
58
  const duplicate_selected_timeline_item_1 = require("./duplicate-selected-timeline-item");
58
59
  const get_sequence_context_menu_items_1 = require("./get-sequence-context-menu-items");
60
+ const get_timeline_media_visualization_layout_1 = require("./get-timeline-media-visualization-layout");
59
61
  const LoopedTimelineIndicators_1 = require("./LoopedTimelineIndicators");
60
62
  const timeline_asset_link_1 = require("./timeline-asset-link");
61
63
  const TimelineImageInfo_1 = require("./TimelineImageInfo");
@@ -159,6 +161,7 @@ const TimelineSequenceInner = ({ s, connectedCompositions, windowWidth, nodePath
159
161
  const video = remotion_1.Internals.useVideo();
160
162
  const maxMediaDuration = (0, use_max_media_duration_1.useMaxMediaDuration)(s, (_d = video === null || video === void 0 ? void 0 : video.fps) !== null && _d !== void 0 ? _d : 30);
161
163
  const effectiveMaxMediaDuration = s.loopDisplay ? null : maxMediaDuration;
164
+ const extendVideoLastFrame = (0, is_video_with_last_frame_hold_1.isVideoWithLastFrameHold)(s);
162
165
  const originalLocation = (0, use_resolved_stack_react_to_change_1.useResolveStackAndReactToChange)(s.getStack);
163
166
  const validatedLocation = (0, react_1.useMemo)(() => {
164
167
  var _a;
@@ -407,6 +410,20 @@ const TimelineSequenceInner = ({ s, connectedCompositions, windowWidth, nodePath
407
410
  video,
408
411
  windowWidth,
409
412
  ]);
413
+ const mediaVisualizationLayout = (0, react_1.useMemo)(() => {
414
+ return (0, get_timeline_media_visualization_layout_1.getTimelineMediaVisualizationLayout)({
415
+ visualizationWidth: width,
416
+ premountWidth: premountWidth !== null && premountWidth !== void 0 ? premountWidth : 0,
417
+ postmountWidth: postmountWidth !== null && postmountWidth !== void 0 ? postmountWidth : 0,
418
+ });
419
+ }, [postmountWidth, premountWidth, width]);
420
+ const mediaVisualizationStyle = (0, react_1.useMemo)(() => {
421
+ return {
422
+ width: mediaVisualizationLayout.width,
423
+ marginLeft: mediaVisualizationLayout.marginLeft,
424
+ height: '100%',
425
+ };
426
+ }, [mediaVisualizationLayout]);
410
427
  const style = (0, react_1.useMemo)(() => {
411
428
  return {
412
429
  background: s.type === 'audio'
@@ -430,21 +447,16 @@ const TimelineSequenceInner = ({ s, connectedCompositions, windowWidth, nodePath
430
447
  nodePath !== null &&
431
448
  validatedLocation !== null &&
432
449
  durationCanUpdate;
433
- const showLeftEdgeDragHandle = (s.type === 'sequence' ||
434
- s.type === 'image' ||
435
- s.type === 'audio' ||
436
- s.type === 'video') &&
437
- !s.isInsideSeries &&
450
+ const showLeftEdgeDragHandle = (0, TimelineSequenceRightEdgeDragHandle_1.isTimelineSequenceLeftEdgeDraggable)(s) &&
438
451
  nodePath !== null &&
439
452
  validatedLocation !== null &&
440
- Boolean(s.controls) &&
441
- fromCanUpdate &&
453
+ ((0, TimelineSequenceRightEdgeDragHandle_1.isCascadingSequence)(s) || fromCanUpdate) &&
442
454
  durationCanUpdate &&
443
455
  trimBeforeCanUpdate;
444
456
  if (maxMediaDuration === null && !s.loopDisplay) {
445
457
  return null;
446
458
  }
447
- const sequence = (jsx_runtime_1.jsxs(TimelineSequenceCurrentFrame, { s: s, displayDurationInFrames: displayDurationInFrames, premountWidth: premountWidth, postmountWidth: postmountWidth, style: style, nodePathInfo: nodePathInfo, sequenceFrameOffset: sequenceFrameOffset, fromCanUpdate: fromCanUpdate, frozenFrame: frozenFrame, onMoveDragPointerDown: onMoveDragPointerDown, onDoubleClick: canHandleSequenceDoubleClick ? onSequenceDoubleClick : undefined, children: [s.type === 'audio' ? (jsx_runtime_1.jsx(AudioWaveform_1.AudioWaveform, { src: s.src, height: timeline_layout_1.TIMELINE_LAYER_HEIGHT_AUDIO, doesVolumeChange: s.doesVolumeChange, visualizationWidth: width, startFrom: s.startMediaFrom, durationInFrames: s.duration, volume: s.volume, playbackRate: s.playbackRate, loopDisplay: s.loopDisplay })) : null, s.type === 'video' ? (jsx_runtime_1.jsx(TimelineVideoInfo_1.TimelineVideoInfo, { src: s.src, visualizationWidth: width, naturalWidth: naturalWidth, startMediaFrom: s.startMediaFrom, mediaFrameAtSequenceZero: s.mediaFrameAtSequenceZero, sequenceFrameOffset: sequenceFrameOffset, durationInFrames: s.duration, playbackRate: s.playbackRate, volume: s.volume, doesVolumeChange: s.doesVolumeChange, premountWidth: premountWidth !== null && premountWidth !== void 0 ? premountWidth : 0, postmountWidth: postmountWidth !== null && postmountWidth !== void 0 ? postmountWidth : 0, loopDisplay: s.loopDisplay, frozenMediaFrame: s.frozenMediaFrame })) : null, s.type === 'image' ? (jsx_runtime_1.jsx(TimelineImageInfo_1.TimelineImageInfo, { src: s.src, visualizationWidth: width })) : null, s.loopDisplay === undefined ? null : (jsx_runtime_1.jsx(LoopedTimelineIndicators_1.LoopedTimelineIndicator, { loops: s.loopDisplay.numberOfTimes })), showLeftEdgeDragHandle && nodePathInfo && validatedLocation ? (jsx_runtime_1.jsx(TimelineSequenceRightEdgeDragHandle_1.TimelineSequenceLeftEdgeDragHandle, { nodePathInfo: nodePathInfo, windowWidth: windowWidth, timelineDurationInFrames: (_h = video.durationInFrames) !== null && _h !== void 0 ? _h : 1 })) : null, showRightEdgeDragHandle && nodePathInfo && validatedLocation ? (jsx_runtime_1.jsx(TimelineSequenceRightEdgeDragHandle_1.TimelineSequenceRightEdgeDragHandle, { nodePathInfo: nodePathInfo, windowWidth: windowWidth, timelineDurationInFrames: (_j = video.durationInFrames) !== null && _j !== void 0 ? _j : 1 })) : null] }));
459
+ const sequence = (jsx_runtime_1.jsxs(TimelineSequenceCurrentFrame, { s: s, displayDurationInFrames: displayDurationInFrames, premountWidth: premountWidth, postmountWidth: postmountWidth, style: style, nodePathInfo: nodePathInfo, sequenceFrameOffset: sequenceFrameOffset, fromCanUpdate: fromCanUpdate, frozenFrame: frozenFrame, onMoveDragPointerDown: onMoveDragPointerDown, onDoubleClick: canHandleSequenceDoubleClick ? onSequenceDoubleClick : undefined, children: [s.type === 'audio' ? (jsx_runtime_1.jsx("div", { style: mediaVisualizationStyle, children: jsx_runtime_1.jsx(AudioWaveform_1.AudioWaveform, { src: s.src, height: timeline_layout_1.TIMELINE_LAYER_HEIGHT_AUDIO, doesVolumeChange: s.doesVolumeChange, visualizationWidth: mediaVisualizationLayout.width, startFrom: s.startMediaFrom, durationInFrames: s.duration, volume: s.volume, playbackRate: s.playbackRate, loopDisplay: s.loopDisplay }) })) : null, s.type === 'video' ? (jsx_runtime_1.jsx(TimelineVideoInfo_1.TimelineVideoInfo, { src: s.src, visualizationWidth: width, naturalWidth: naturalWidth, startMediaFrom: s.startMediaFrom, mediaFrameAtSequenceZero: s.mediaFrameAtSequenceZero, sequenceFrameOffset: sequenceFrameOffset, durationInFrames: s.duration, playbackRate: s.playbackRate, volume: s.volume, doesVolumeChange: s.doesVolumeChange, premountWidth: premountWidth !== null && premountWidth !== void 0 ? premountWidth : 0, postmountWidth: postmountWidth !== null && postmountWidth !== void 0 ? postmountWidth : 0, loopDisplay: s.loopDisplay, frozenMediaFrame: s.frozenMediaFrame, extendLastFrame: extendVideoLastFrame })) : null, s.type === 'image' ? (jsx_runtime_1.jsx("div", { style: mediaVisualizationStyle, children: jsx_runtime_1.jsx(TimelineImageInfo_1.TimelineImageInfo, { src: s.src, visualizationWidth: mediaVisualizationLayout.width }) })) : null, s.loopDisplay === undefined ? null : (jsx_runtime_1.jsx(LoopedTimelineIndicators_1.LoopedTimelineIndicator, { loops: s.loopDisplay.numberOfTimes })), showLeftEdgeDragHandle && nodePathInfo && validatedLocation ? (jsx_runtime_1.jsx(TimelineSequenceRightEdgeDragHandle_1.TimelineSequenceLeftEdgeDragHandle, { nodePathInfo: nodePathInfo, windowWidth: windowWidth, timelineDurationInFrames: (_h = video.durationInFrames) !== null && _h !== void 0 ? _h : 1 })) : null, showRightEdgeDragHandle && nodePathInfo && validatedLocation ? (jsx_runtime_1.jsx(TimelineSequenceRightEdgeDragHandle_1.TimelineSequenceRightEdgeDragHandle, { nodePathInfo: nodePathInfo, windowWidth: windowWidth, timelineDurationInFrames: (_j = video.durationInFrames) !== null && _j !== void 0 ? _j : 1 })) : null] }));
448
460
  return previewConnected ? (jsx_runtime_1.jsx(ContextMenu_1.ContextMenu, { values: contextMenuValues, onOpen: onContextMenuOpen, children: sequence })) : (sequence);
449
461
  };
450
462
  exports.TimelineSequence = react_1.default.memo(TimelineSequenceFn);
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TimelineSequenceFrame = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const colors_1 = require("../../helpers/colors");
6
+ const snowflake_1 = require("../../icons/snowflake");
6
7
  const relativeFrameStyle = {
7
8
  alignItems: 'center',
8
9
  display: 'flex',
@@ -20,11 +21,8 @@ const snowflakeStyle = {
20
21
  height: 12,
21
22
  width: 12,
22
23
  };
23
- const FreezeFrameIcon = () => {
24
- return (jsx_runtime_1.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 512 512", style: snowflakeStyle, fill: colors_1.CURRENT_COLOR, children: jsx_runtime_1.jsx("path", { d: "M288 32l0-32-64 0 0 88.4-64-64-39.6 39.6 103.6 103.6 0 56.4-56.4 0-103.6-103.6-39.6 39.6 64 64-88.4 0 0 64 88.4 0c-33.5 33.5-54.9 54.9-64 64L64 391.6c2.5-2.5 37.1-37.1 103.6-103.6l56.4 0 0 56.4C157.5 410.9 122.9 445.5 120.4 448L160 487.6c9.1-9.1 30.5-30.5 64-64l0 88.4 64 0 0-88.4 64 64 39.6-39.6-103.6-103.6 0-56.4 56.4 0 103.6 103.6 39.6-39.6-64-64 88.4 0 0-64-88.4 0c33.5-33.5 54.9-54.9 64-64L448 120.4c-2.5 2.5-37.1 37.1-103.6 103.6l-56.4 0 0-56.4C354.5 101.1 389.1 66.5 391.6 64L352 24.4c-9.1 9.1-30.5 30.5-64 64L288 32z" }) }));
25
- };
26
24
  const TimelineSequenceFrame = ({ roundedFrame, frozenFrame, premounted, postmounted }) => {
27
- return (jsx_runtime_1.jsxs("div", { style: relativeFrameStyle, children: [frozenFrame === null ? null : jsx_runtime_1.jsx(FreezeFrameIcon, {}), frozenFrame !== null && frozenFrame !== void 0 ? frozenFrame : (premounted
25
+ return (jsx_runtime_1.jsxs("div", { style: relativeFrameStyle, children: [frozenFrame === null ? null : (jsx_runtime_1.jsx(snowflake_1.SnowflakeIcon, { style: snowflakeStyle, color: colors_1.CURRENT_COLOR })), frozenFrame !== null && frozenFrame !== void 0 ? frozenFrame : (premounted
28
26
  ? '0 (Premounted)'
29
27
  : postmounted !== null
30
28
  ? `${postmounted} (Postmounted)`
@@ -504,6 +504,8 @@ const TimelineSequenceItem = ({ children, connectedCompositions, nestedDepth, se
504
504
  ? JSON.stringify(fieldSchema.default)
505
505
  : null;
506
506
  (0, save_sequence_prop_1.saveSequenceProps)({
507
+ addedKeyframes: null,
508
+ movedKeyframes: null,
507
509
  changes: [
508
510
  {
509
511
  fileName: validatedLocation.source,
@@ -77,6 +77,8 @@ const Value = ({ field, nodePath, validatedLocation, schema, propStatus }) => {
77
77
  return Promise.resolve();
78
78
  }
79
79
  return (0, save_sequence_prop_1.saveSequenceProps)({
80
+ addedKeyframes: null,
81
+ movedKeyframes: null,
80
82
  changes: [
81
83
  {
82
84
  fileName: validatedLocation.source,
@@ -219,6 +221,8 @@ const TimelineSequencePropItem = ({ field, validatedLocation, rowDepth, nodePath
219
221
  : null;
220
222
  const fieldLabel = (_a = field.description) !== null && _a !== void 0 ? _a : field.key;
221
223
  (0, save_sequence_prop_1.saveSequenceProps)({
224
+ addedKeyframes: null,
225
+ movedKeyframes: null,
222
226
  changes: [
223
227
  {
224
228
  fileName: validatedLocation.source,
@@ -7,6 +7,7 @@ import { type TimelineSelection } from './TimelineSelection';
7
7
  export type TimelineSequenceDurationDragTarget = {
8
8
  readonly fileName: string;
9
9
  readonly initialDuration: number;
10
+ readonly minimumDuration: number;
10
11
  readonly nodePath: SequencePropsSubscriptionKey;
11
12
  readonly schema: InteractivitySchema;
12
13
  };
@@ -15,7 +16,10 @@ export type TimelineSequenceLeftEdgeDragTarget = {
15
16
  readonly initialDuration: number;
16
17
  readonly initialFrom: number;
17
18
  readonly initialTrimBefore: number;
19
+ readonly minimumDuration: number;
18
20
  readonly nodePath: SequencePropsSubscriptionKey;
21
+ readonly playbackRate: number;
22
+ readonly positionField: 'from' | null;
19
23
  readonly schema: InteractivitySchema;
20
24
  };
21
25
  export type TimelineSequenceFromDragTarget = {
@@ -33,21 +37,29 @@ type TimelineSequenceKeyframeDragTarget = {
33
37
  type TimelineSequenceEffectKeyframeDragTarget = TimelineSequenceKeyframeDragTarget & {
34
38
  readonly effectIndex: number;
35
39
  };
40
+ export declare const isTransitionSeriesSequence: (sequence: TSequence) => boolean;
41
+ export declare const isCascadingSequence: (sequence: TSequence) => boolean;
36
42
  export declare const isTimelineSequenceDurationDraggable: (sequence: TSequence) => boolean;
37
- export declare const getTimelineSequenceDurationDragValue: ({ initialDuration, deltaFrames, }: {
43
+ export declare const isTimelineSequenceLeftEdgeDraggable: (sequence: TSequence) => boolean;
44
+ export declare const getTimelineSequenceDurationDragValue: ({ initialDuration, deltaFrames, minimumDuration, }: {
38
45
  readonly initialDuration: number;
39
46
  readonly deltaFrames: number;
47
+ readonly minimumDuration?: number | undefined;
40
48
  }) => number;
41
- export declare const getTimelineSequenceLeftEdgeDragDelta: ({ initialDuration, initialTrimBefore, deltaFrames, }: {
49
+ export declare const getTimelineSequenceLeftEdgeDragDelta: ({ initialDuration, initialTrimBefore, deltaFrames, playbackRate, minimumDuration, }: {
42
50
  readonly initialDuration: number;
43
51
  readonly initialTrimBefore: number;
44
52
  readonly deltaFrames: number;
53
+ readonly playbackRate: number;
54
+ readonly minimumDuration?: number | undefined;
45
55
  }) => number;
46
- export declare const getTimelineSequenceLeftEdgeDragValues: ({ initialDuration, initialFrom, initialTrimBefore, deltaFrames, }: {
56
+ export declare const getTimelineSequenceLeftEdgeDragValues: ({ initialDuration, initialFrom, initialTrimBefore, deltaFrames, playbackRate, minimumDuration, }: {
47
57
  readonly initialDuration: number;
48
58
  readonly initialFrom: number;
49
59
  readonly initialTrimBefore: number;
50
60
  readonly deltaFrames: number;
61
+ readonly playbackRate: number;
62
+ readonly minimumDuration?: number | undefined;
51
63
  }) => {
52
64
  durationInFrames: number;
53
65
  from: number;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TimelineSequenceRightEdgeDragHandle = exports.useTimelineSequenceFromDrag = exports.TimelineSequenceLeftEdgeDragHandle = exports.getTimelineSequenceFromDragTargets = exports.getTimelineSequenceLeftEdgeDragTargets = exports.getTimelineSequenceDurationDragTargets = exports.getTimelineSequenceFromDragKeyframeMoves = exports.getTimelineSequenceFromDragChanges = exports.getTimelineSequenceFromDragValue = exports.getTimelineSequenceDurationDragChanges = exports.getTimelineSequenceLeftEdgeDragChanges = exports.getTimelineSequenceLeftEdgeDragValues = exports.getTimelineSequenceLeftEdgeDragDelta = exports.getTimelineSequenceDurationDragValue = exports.isTimelineSequenceDurationDraggable = void 0;
3
+ exports.TimelineSequenceRightEdgeDragHandle = exports.useTimelineSequenceFromDrag = exports.TimelineSequenceLeftEdgeDragHandle = exports.getTimelineSequenceFromDragTargets = exports.getTimelineSequenceLeftEdgeDragTargets = exports.getTimelineSequenceDurationDragTargets = exports.getTimelineSequenceFromDragKeyframeMoves = exports.getTimelineSequenceFromDragChanges = exports.getTimelineSequenceFromDragValue = exports.getTimelineSequenceDurationDragChanges = exports.getTimelineSequenceLeftEdgeDragChanges = exports.getTimelineSequenceLeftEdgeDragValues = exports.getTimelineSequenceLeftEdgeDragDelta = exports.getTimelineSequenceDurationDragValue = exports.isTimelineSequenceLeftEdgeDraggable = exports.isTimelineSequenceDurationDraggable = exports.isCascadingSequence = exports.isTransitionSeriesSequence = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const studio_shared_1 = require("@remotion/studio-shared");
6
6
  const react_1 = require("react");
@@ -9,6 +9,7 @@ const no_react_1 = require("remotion/no-react");
9
9
  const calculate_timeline_1 = require("../../helpers/calculate-timeline");
10
10
  const client_id_1 = require("../../helpers/client-id");
11
11
  const colors_1 = require("../../helpers/colors");
12
+ const sort_by_nonce_history_1 = require("../../helpers/sort-by-nonce-history");
12
13
  const timeline_layout_1 = require("../../helpers/timeline-layout");
13
14
  const ForceSpecificCursor_1 = require("../ForceSpecificCursor");
14
15
  const save_sequence_prop_1 = require("./save-sequence-prop");
@@ -81,50 +82,102 @@ const canUpdateTrimBefore = ({ propStatuses, nodePath, }) => {
81
82
  const status = (_b = (_a = remotion_1.Internals.getPropStatusesCtx(propStatuses, nodePath)) === null || _a === void 0 ? void 0 : _a.trimBefore) === null || _b === void 0 ? void 0 : _b.status;
82
83
  return status === 'static';
83
84
  };
84
- const isTimelineSequenceDurationDraggable = (sequence) => {
85
+ const isTransitionSeriesSequence = (sequence) => {
86
+ var _a;
87
+ return ((_a = sequence.controls) === null || _a === void 0 ? void 0 : _a.componentIdentity) ===
88
+ 'dev.remotion.transitions.TransitionSeries.Sequence';
89
+ };
90
+ exports.isTransitionSeriesSequence = isTransitionSeriesSequence;
91
+ const isSeriesSequence = (sequence) => {
85
92
  var _a;
86
- const isInteractiveSeriesSequence = ((_a = sequence.controls) === null || _a === void 0 ? void 0 : _a.componentIdentity) ===
93
+ return ((_a = sequence.controls) === null || _a === void 0 ? void 0 : _a.componentIdentity) ===
87
94
  'dev.remotion.remotion.Series.Sequence';
95
+ };
96
+ const isCascadingSequence = (sequence) => isSeriesSequence(sequence) || (0, exports.isTransitionSeriesSequence)(sequence);
97
+ exports.isCascadingSequence = isCascadingSequence;
98
+ const isTransitionSeriesTransition = (sequence) => {
99
+ var _a;
100
+ return ((_a = sequence === null || sequence === void 0 ? void 0 : sequence.controls) === null || _a === void 0 ? void 0 : _a.componentIdentity) ===
101
+ 'dev.remotion.transitions.TransitionSeries.Transition';
102
+ };
103
+ const getMinimumSequenceDuration = ({ sequence, sequences, }) => {
104
+ if (!(0, exports.isTransitionSeriesSequence)(sequence)) {
105
+ return 1;
106
+ }
107
+ const siblings = (0, sort_by_nonce_history_1.sortItemsByNonceHistory)(sequences.filter((candidate) => candidate.parent === sequence.parent &&
108
+ candidate.rootId === sequence.rootId &&
109
+ ((0, exports.isTransitionSeriesSequence)(candidate) ||
110
+ isTransitionSeriesTransition(candidate))));
111
+ const sequenceIndex = siblings.findIndex((candidate) => candidate.id === sequence.id);
112
+ if (sequenceIndex === -1) {
113
+ return 1;
114
+ }
115
+ const previous = siblings[sequenceIndex - 1];
116
+ const next = siblings[sequenceIndex + 1];
117
+ return Math.max(1, isTransitionSeriesTransition(previous) ? previous.duration : 1, isTransitionSeriesTransition(next) ? next.duration : 1);
118
+ };
119
+ const isTimelineSequenceDurationDraggable = (sequence) => {
120
+ const isInteractiveCascadingSequence = (0, exports.isCascadingSequence)(sequence);
88
121
  return ((sequence.type === 'sequence' ||
89
122
  sequence.type === 'image' ||
90
123
  sequence.type === 'audio' ||
91
124
  sequence.type === 'video') &&
92
125
  !sequence.loopDisplay &&
93
- (!sequence.isInsideSeries || isInteractiveSeriesSequence) &&
126
+ (!sequence.isInsideSeries || isInteractiveCascadingSequence) &&
94
127
  Boolean(sequence.controls));
95
128
  };
96
129
  exports.isTimelineSequenceDurationDraggable = isTimelineSequenceDurationDraggable;
97
- const isLeftEdgeDraggableSequence = (sequence) => {
98
- return (!sequence.isInsideSeries &&
130
+ const isTimelineSequenceLeftEdgeDraggable = (sequence) => {
131
+ return ((!sequence.isInsideSeries || (0, exports.isCascadingSequence)(sequence)) &&
99
132
  Boolean(sequence.controls) &&
100
133
  (sequence.type === 'sequence' ||
101
134
  sequence.type === 'image' ||
102
135
  sequence.type === 'audio' ||
103
136
  sequence.type === 'video'));
104
137
  };
138
+ exports.isTimelineSequenceLeftEdgeDraggable = isTimelineSequenceLeftEdgeDraggable;
139
+ const playbackRateComponentIdentities = new Set([
140
+ 'dev.remotion.gif.Gif',
141
+ 'dev.remotion.media.Audio',
142
+ 'dev.remotion.media.Video',
143
+ 'dev.remotion.remotion.AnimatedImage',
144
+ ]);
145
+ const getTrimBeforePlaybackRate = (sequence) => {
146
+ var _a, _b;
147
+ const componentIdentity = (_a = sequence.controls) === null || _a === void 0 ? void 0 : _a.componentIdentity;
148
+ if (componentIdentity === null ||
149
+ componentIdentity === undefined ||
150
+ !playbackRateComponentIdentities.has(componentIdentity)) {
151
+ return 1;
152
+ }
153
+ const runtimePlaybackRate = (_b = sequence.controls) === null || _b === void 0 ? void 0 : _b.currentRuntimeValueDotNotation.playbackRate;
154
+ return typeof runtimePlaybackRate === 'number' ? runtimePlaybackRate : 1;
155
+ };
105
156
  const isFromDraggableSequence = (sequence) => {
106
157
  return (!sequence.loopDisplay &&
107
158
  !sequence.isInsideSeries &&
108
159
  Boolean(sequence.controls));
109
160
  };
110
- const getTimelineSequenceDurationDragValue = ({ initialDuration, deltaFrames, }) => Math.max(1, initialDuration + deltaFrames);
161
+ const getTimelineSequenceDurationDragValue = ({ initialDuration, deltaFrames, minimumDuration = 1, }) => Math.max(minimumDuration, initialDuration + deltaFrames);
111
162
  exports.getTimelineSequenceDurationDragValue = getTimelineSequenceDurationDragValue;
112
- const getTimelineSequenceLeftEdgeDragDelta = ({ initialDuration, initialTrimBefore, deltaFrames, }) => {
113
- const minDeltaFrames = 0 - initialTrimBefore;
114
- const maxDeltaFrames = initialDuration - 1;
163
+ const getTimelineSequenceLeftEdgeDragDelta = ({ initialDuration, initialTrimBefore, deltaFrames, playbackRate, minimumDuration = 1, }) => {
164
+ const minDeltaFrames = 0 - initialTrimBefore / playbackRate;
165
+ const maxDeltaFrames = initialDuration - minimumDuration;
115
166
  return Math.max(minDeltaFrames, Math.min(deltaFrames, maxDeltaFrames));
116
167
  };
117
168
  exports.getTimelineSequenceLeftEdgeDragDelta = getTimelineSequenceLeftEdgeDragDelta;
118
- const getTimelineSequenceLeftEdgeDragValues = ({ initialDuration, initialFrom, initialTrimBefore, deltaFrames, }) => {
169
+ const getTimelineSequenceLeftEdgeDragValues = ({ initialDuration, initialFrom, initialTrimBefore, deltaFrames, playbackRate, minimumDuration = 1, }) => {
119
170
  const clampedDeltaFrames = (0, exports.getTimelineSequenceLeftEdgeDragDelta)({
120
171
  initialDuration,
121
172
  initialTrimBefore,
122
173
  deltaFrames,
174
+ playbackRate,
175
+ minimumDuration,
123
176
  });
124
177
  return {
125
178
  durationInFrames: initialDuration - clampedDeltaFrames,
126
179
  from: initialFrom + clampedDeltaFrames,
127
- trimBefore: initialTrimBefore + clampedDeltaFrames,
180
+ trimBefore: initialTrimBefore + clampedDeltaFrames * playbackRate,
128
181
  };
129
182
  };
130
183
  exports.getTimelineSequenceLeftEdgeDragValues = getTimelineSequenceLeftEdgeDragValues;
@@ -135,13 +188,16 @@ const getTimelineSequenceLeftEdgeDragChanges = ({ targets, deltaFrames, }) => {
135
188
  initialFrom: target.initialFrom,
136
189
  initialTrimBefore: target.initialTrimBefore,
137
190
  deltaFrames,
191
+ playbackRate: target.playbackRate,
192
+ minimumDuration: target.minimumDuration,
138
193
  });
139
194
  const changes = [];
140
- if (nextValues.from !== target.initialFrom) {
195
+ if (target.positionField !== null &&
196
+ nextValues.from !== target.initialFrom) {
141
197
  changes.push({
142
198
  fileName: target.fileName,
143
199
  nodePath: target.nodePath,
144
- fieldKey: 'from',
200
+ fieldKey: target.positionField,
145
201
  value: nextValues.from,
146
202
  defaultValue: '0',
147
203
  schema: target.schema,
@@ -176,6 +232,7 @@ const getTimelineSequenceDurationDragChanges = ({ targets, deltaFrames, }) => {
176
232
  const nextValue = (0, exports.getTimelineSequenceDurationDragValue)({
177
233
  initialDuration: target.initialDuration,
178
234
  deltaFrames,
235
+ minimumDuration: target.minimumDuration,
179
236
  });
180
237
  if (nextValue === target.initialDuration) {
181
238
  return [];
@@ -289,6 +346,10 @@ const getTimelineSequenceDurationDragTargets = ({ draggedNodePathInfo, selectedI
289
346
  targets.set(key, {
290
347
  fileName: nodePath.absolutePath,
291
348
  initialDuration: originalSequence.duration,
349
+ minimumDuration: getMinimumSequenceDuration({
350
+ sequence: originalSequence,
351
+ sequences,
352
+ }),
292
353
  nodePath,
293
354
  schema: controls.schema,
294
355
  });
@@ -320,12 +381,13 @@ const getTimelineSequenceLeftEdgeDragTargets = ({ draggedNodePathInfo, selectedI
320
381
  if (!track ||
321
382
  !track.nodePathInfo ||
322
383
  !originalSequence ||
323
- !isLeftEdgeDraggableSequence(originalSequence)) {
384
+ !(0, exports.isTimelineSequenceLeftEdgeDraggable)(originalSequence)) {
324
385
  return null;
325
386
  }
326
387
  const nodePath = track.nodePathInfo.sequenceSubscriptionKey;
327
388
  const trimsMedia = originalSequence.type === 'audio' || originalSequence.type === 'video';
328
- if (!canUpdateFrom({ propStatuses, nodePath }) ||
389
+ const positionField = (0, exports.isCascadingSequence)(originalSequence) ? null : 'from';
390
+ if ((positionField === 'from' && !canUpdateFrom({ propStatuses, nodePath })) ||
329
391
  !canUpdateDurationInFrames({ propStatuses, nodePath }) ||
330
392
  !canUpdateTrimBefore({ propStatuses, nodePath })) {
331
393
  return null;
@@ -339,11 +401,17 @@ const getTimelineSequenceLeftEdgeDragTargets = ({ draggedNodePathInfo, selectedI
339
401
  targets.set(key, {
340
402
  fileName: nodePath.absolutePath,
341
403
  initialDuration: originalSequence.duration,
342
- initialFrom: originalSequence.from,
404
+ initialFrom: positionField === 'from' ? originalSequence.from : 0,
343
405
  initialTrimBefore: trimsMedia
344
406
  ? ((_a = originalSequence.trimBefore) !== null && _a !== void 0 ? _a : Math.max(0, originalSequence.startMediaFrom))
345
407
  : ((_b = originalSequence.trimBefore) !== null && _b !== void 0 ? _b : 0),
408
+ minimumDuration: getMinimumSequenceDuration({
409
+ sequence: originalSequence,
410
+ sequences,
411
+ }),
346
412
  nodePath,
413
+ playbackRate: getTrimBeforePlaybackRate(originalSequence),
414
+ positionField,
347
415
  schema: controls.schema,
348
416
  });
349
417
  }
@@ -468,6 +536,8 @@ const TimelineSequenceLeftEdgeDragHandle = ({ nodePathInfo, windowWidth, timelin
468
536
  return;
469
537
  }
470
538
  const savePromise = (0, save_sequence_prop_1.saveSequenceProps)({
539
+ addedKeyframes: null,
540
+ movedKeyframes: null,
471
541
  changes,
472
542
  setPropStatuses: latestSetPropStatuses,
473
543
  clientId: latestServerState.clientId,
@@ -549,8 +619,12 @@ const TimelineSequenceLeftEdgeDragHandle = ({ nodePathInfo, windowWidth, timelin
549
619
  initialFrom: target.initialFrom,
550
620
  initialTrimBefore: target.initialTrimBefore,
551
621
  deltaFrames,
622
+ playbackRate: target.playbackRate,
623
+ minimumDuration: target.minimumDuration,
552
624
  });
553
- latestRef.current.setDragOverrides(target.nodePath, 'from', remotion_1.Internals.makeStaticDragOverride(nextValues.from));
625
+ if (target.positionField !== null) {
626
+ latestRef.current.setDragOverrides(target.nodePath, target.positionField, remotion_1.Internals.makeStaticDragOverride(nextValues.from));
627
+ }
554
628
  latestRef.current.setDragOverrides(target.nodePath, 'durationInFrames', remotion_1.Internals.makeStaticDragOverride(nextValues.durationInFrames));
555
629
  latestRef.current.setDragOverrides(target.nodePath, 'trimBefore', remotion_1.Internals.makeStaticDragOverride(nextValues.trimBefore));
556
630
  }
@@ -651,6 +725,7 @@ const useTimelineSequenceFromDrag = ({ nodePathInfo, windowWidth, timelineDurati
651
725
  return;
652
726
  }
653
727
  const savePromise = (0, save_sequence_prop_1.saveSequenceProps)({
728
+ addedKeyframes: null,
654
729
  changes,
655
730
  movedKeyframes: {
656
731
  sequenceKeyframes: keyframeMoves.sequenceKeyframes,
@@ -843,6 +918,8 @@ const TimelineSequenceRightEdgeDragHandle = ({ nodePathInfo, windowWidth, timeli
843
918
  return;
844
919
  }
845
920
  const savePromise = (0, save_sequence_prop_1.saveSequenceProps)({
921
+ addedKeyframes: null,
922
+ movedKeyframes: null,
846
923
  changes,
847
924
  setPropStatuses: latestSetPropStatuses,
848
925
  clientId: latestServerState.clientId,
@@ -923,6 +1000,7 @@ const TimelineSequenceRightEdgeDragHandle = ({ nodePathInfo, windowWidth, timeli
923
1000
  latestRef.current.setDragOverrides(target.nodePath, 'durationInFrames', remotion_1.Internals.makeStaticDragOverride((0, exports.getTimelineSequenceDurationDragValue)({
924
1001
  initialDuration: target.initialDuration,
925
1002
  deltaFrames,
1003
+ minimumDuration: target.minimumDuration,
926
1004
  })));
927
1005
  }
928
1006
  };
@@ -2,4 +2,20 @@ import React from 'react';
2
2
  export declare const TIMELINE_TIME_INDICATOR_HEIGHT = 39;
3
3
  export declare const TimelineTimePlaceholders: React.FC;
4
4
  export declare const TimelineTimePadding: React.FC;
5
+ export declare const getNiceSecondInterval: (rawNthSecond: number) => number;
6
+ type TickInterval = {
7
+ readonly interval: number;
8
+ readonly unit: 'frames' | 'seconds';
9
+ };
10
+ export type TimelineTickScale = {
11
+ readonly labelEverySeconds: number;
12
+ readonly mediumTickEvery: TickInterval | null;
13
+ readonly minorTickEvery: TickInterval | null;
14
+ };
15
+ export declare const getTimelineTickScale: ({ fps, frameInterval, rawSecondMarkerEveryNth, }: {
16
+ readonly fps: number;
17
+ readonly frameInterval: number;
18
+ readonly rawSecondMarkerEveryNth: number;
19
+ }) => TimelineTickScale;
5
20
  export declare const TimelineTimeIndicators: React.FC;
21
+ export {};