@remotion/studio 4.0.520 → 4.0.522

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 (117) hide show
  1. package/dist/api/shut-down-studio.d.ts +6 -0
  2. package/dist/api/shut-down-studio.js +23 -0
  3. package/dist/components/AudioWaveform.js +10 -6
  4. package/dist/components/Canvas.js +84 -12
  5. package/dist/components/CanvasIfSizeIsAvailable.js +7 -0
  6. package/dist/components/CaptionInspector.d.ts +1 -0
  7. package/dist/components/CaptionInspector.js +43 -2
  8. package/dist/components/CaptionTextEditor.js +1 -1
  9. package/dist/components/CompositionSelector.js +41 -30
  10. package/dist/components/CompositionSelectorItem.d.ts +7 -0
  11. package/dist/components/CompositionSelectorItem.js +343 -67
  12. package/dist/components/CopyButton.js +7 -14
  13. package/dist/components/Editor.js +6 -5
  14. package/dist/components/EditorContent.js +1 -1
  15. package/dist/components/ElementInstallConfirmation.js +77 -65
  16. package/dist/components/ElementLibraryModal.js +3 -1
  17. package/dist/components/FixComputedValueModal.js +20 -10
  18. package/dist/components/InlineCaptionInspector.js +37 -1
  19. package/dist/components/InspectorLocationCopy.js +10 -5
  20. package/dist/components/InspectorPanel/ElementLibraryButton.js +3 -18
  21. package/dist/components/InspectorSequenceSection.js +1 -4
  22. package/dist/components/Menu/MenuSubItem.js +1 -1
  23. package/dist/components/MenuBuildIndicator.js +7 -2
  24. package/dist/components/MenuCompositionName.js +62 -6
  25. package/dist/components/ModalContainer.d.ts +1 -0
  26. package/dist/components/ModalContainer.js +2 -2
  27. package/dist/components/ModalHeader.js +5 -1
  28. package/dist/components/QuickSwitcher/asset-search.d.ts +0 -1
  29. package/dist/components/QuickSwitcher/asset-search.js +1 -16
  30. package/dist/components/RenderButton.js +2 -2
  31. package/dist/components/RenderModal/CliCopyButton.js +13 -27
  32. package/dist/components/RenderModal/RenderStatusModal.js +7 -1
  33. package/dist/components/RenderModal/ServerRenderModal.js +1 -1
  34. package/dist/components/RenderModal/WebRenderModal.js +1 -1
  35. package/dist/components/RenderQueue/ClientRenderQueueProcessor.js +1 -1
  36. package/dist/components/RenderQueue/RenderQueueCopyToClipboard.js +7 -4
  37. package/dist/components/SettingsModal.js +8 -5
  38. package/dist/components/SidebarCollapserControls.js +11 -5
  39. package/dist/components/SkillsSettings.js +9 -5
  40. package/dist/components/Splitter/SplitterContainer.js +63 -10
  41. package/dist/components/Splitter/SplitterContext.d.ts +3 -0
  42. package/dist/components/Splitter/SplitterContext.js +5 -1
  43. package/dist/components/Splitter/SplitterElement.js +11 -2
  44. package/dist/components/Splitter/SplitterHandle.d.ts +1 -0
  45. package/dist/components/Splitter/SplitterHandle.js +55 -25
  46. package/dist/components/TimeValue.js +36 -7
  47. package/dist/components/Timeline/SubscribeToNodePaths.d.ts +2 -1
  48. package/dist/components/Timeline/SubscribeToNodePaths.js +2 -1
  49. package/dist/components/Timeline/Timeline.d.ts +1 -1
  50. package/dist/components/Timeline/Timeline.js +45 -22
  51. package/dist/components/Timeline/TimelineAssetField.d.ts +0 -1
  52. package/dist/components/Timeline/TimelineAssetField.js +16 -9
  53. package/dist/components/Timeline/TimelineCollapseToggle.js +1 -1
  54. package/dist/components/Timeline/TimelineDragHandler.js +9 -4
  55. package/dist/components/Timeline/TimelineFontWeightField.d.ts +11 -0
  56. package/dist/components/Timeline/TimelineFontWeightField.js +65 -0
  57. package/dist/components/Timeline/TimelineLayerChildren.d.ts +21 -0
  58. package/dist/components/Timeline/TimelineLayerChildren.js +129 -0
  59. package/dist/components/Timeline/TimelineNumberField.js +13 -5
  60. package/dist/components/Timeline/TimelinePinchZoom.js +6 -30
  61. package/dist/components/Timeline/TimelinePlayCursorSyncer.js +1 -7
  62. package/dist/components/Timeline/TimelinePrimitiveFieldValue.js +4 -0
  63. package/dist/components/Timeline/TimelineSequence.js +113 -42
  64. package/dist/components/Timeline/TimelineSequenceItem.js +14 -2
  65. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.d.ts +13 -3
  66. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +185 -126
  67. package/dist/components/Timeline/TimelineSlider.js +1 -4
  68. package/dist/components/Timeline/TimelineTickFormatProvider.d.ts +8 -0
  69. package/dist/components/Timeline/TimelineTickFormatProvider.js +16 -0
  70. package/dist/components/Timeline/TimelineTimeIndicators.js +7 -3
  71. package/dist/components/Timeline/TimelineVideoInfo.js +7 -3
  72. package/dist/components/Timeline/TimelineWidthProvider.js +2 -5
  73. package/dist/components/Timeline/TimelineZoomControls.js +20 -20
  74. package/dist/components/Timeline/get-sequence-split-menu-item.d.ts +11 -0
  75. package/dist/components/Timeline/get-sequence-split-menu-item.js +55 -0
  76. package/dist/components/Timeline/timeline-field-display-utils.js +1 -0
  77. package/dist/components/Timeline/use-sequence-props-subscription.d.ts +3 -2
  78. package/dist/components/Timeline/use-sequence-props-subscription.js +4 -10
  79. package/dist/components/TopPanel.js +3 -19
  80. package/dist/components/UpdateStatusContext.d.ts +5 -0
  81. package/dist/components/UpdateStatusContext.js +53 -2
  82. package/dist/components/UpdatesSettings.js +34 -9
  83. package/dist/components/WebMcp.js +26 -0
  84. package/dist/components/ZoomPersistor.js +6 -3
  85. package/dist/components/composition-menu-items.js +1 -1
  86. package/dist/components/composition-selector-drag-data.d.ts +27 -0
  87. package/dist/components/composition-selector-drag-data.js +80 -0
  88. package/dist/components/import-assets.d.ts +2 -1
  89. package/dist/components/import-assets.js +11 -1
  90. package/dist/components/parse-caption-file.d.ts +5 -0
  91. package/dist/components/parse-caption-file.js +63 -0
  92. package/dist/esm/{chunk-np6q13k5.js → chunk-3netyjd9.js} +7943 -6314
  93. package/dist/esm/index.mjs +23 -8
  94. package/dist/esm/internals.mjs +7965 -6336
  95. package/dist/esm/previewEntry.mjs +8007 -6378
  96. package/dist/esm/renderEntry.mjs +1 -1
  97. package/dist/helpers/copy-text.js +1 -2
  98. package/dist/helpers/get-preview-file-type.js +22 -3
  99. package/dist/helpers/inserted-element-selection.d.ts +2 -1
  100. package/dist/helpers/use-copy-feedback.d.ts +4 -0
  101. package/dist/helpers/use-copy-feedback.js +19 -0
  102. package/dist/helpers/use-menu-structure.js +2 -2
  103. package/dist/icons/copy.d.ts +5 -0
  104. package/dist/icons/copy.js +12 -0
  105. package/dist/index.d.ts +1 -0
  106. package/dist/index.js +3 -1
  107. package/dist/state/canvas-ref.d.ts +1 -0
  108. package/dist/state/canvas-ref.js +2 -1
  109. package/dist/state/modals.d.ts +0 -2
  110. package/dist/state/sidebar.d.ts +3 -0
  111. package/dist/state/sidebar.js +6 -1
  112. package/dist/state/timeline-zoom.d.ts +1 -1
  113. package/dist/state/timeline-zoom.js +3 -3
  114. package/dist/visual-controls/VisualControls.js +4 -0
  115. package/package.json +16 -16
  116. package/dist/helpers/use-max-media-duration.d.ts +0 -2
  117. package/dist/helpers/use-max-media-duration.js +0 -61
@@ -0,0 +1,129 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TimelineLayerChildrenToggle = exports.useTimelineLayerChildren = exports.TimelineLayerChildrenProvider = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const colors_1 = require("../../helpers/colors");
7
+ const hoverable_1 = require("../../helpers/hoverable");
8
+ const persist_boolean_map_1 = require("../../helpers/persist-boolean-map");
9
+ const timeline_node_path_key_1 = require("../../helpers/timeline-node-path-key");
10
+ const TimelineCollapseToggle_1 = require("./TimelineCollapseToggle");
11
+ const TimelineExpandArrowButton_1 = require("./TimelineExpandArrowButton");
12
+ const STORAGE_KEY = 'remotion.editor.collapsedLayerChildren.v1';
13
+ const TimelineLayerChildrenContext = (0, react_1.createContext)(null);
14
+ exports.TimelineLayerChildrenProvider = TimelineLayerChildrenContext.Provider;
15
+ const useTimelineLayerChildren = (tracks, sequences, compositionId) => {
16
+ const [collapsed, setCollapsed] = (0, react_1.useState)(() => {
17
+ var _a;
18
+ try {
19
+ const parsed = JSON.parse((_a = window.localStorage.getItem(STORAGE_KEY)) !== null && _a !== void 0 ? _a : '{}');
20
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
21
+ return {};
22
+ }
23
+ return Object.fromEntries(Object.entries(parsed).filter(([, storedValue]) => storedValue === true));
24
+ }
25
+ catch (_b) {
26
+ return {};
27
+ }
28
+ });
29
+ const toggle = (0, react_1.useCallback)((key) => {
30
+ setCollapsed((previous) => {
31
+ const next = (0, persist_boolean_map_1.toggleBooleanMapKey)(previous, key);
32
+ try {
33
+ window.localStorage.setItem(STORAGE_KEY, JSON.stringify(next));
34
+ }
35
+ catch (_a) {
36
+ // Keep the control usable when storage is unavailable.
37
+ }
38
+ return next;
39
+ });
40
+ }, []);
41
+ const hierarchy = (0, react_1.useMemo)(() => {
42
+ var _a;
43
+ var _b, _c;
44
+ const byId = new Map(sequences.map((sequence) => [sequence.id, sequence]));
45
+ const siblingIndices = new Map();
46
+ const siblingCounts = new Map();
47
+ for (const sequence of sequences) {
48
+ const index = (_b = siblingCounts.get(sequence.parent)) !== null && _b !== void 0 ? _b : 0;
49
+ siblingIndices.set(sequence.id, index);
50
+ siblingCounts.set(sequence.parent, index + 1);
51
+ }
52
+ const keys = new Map();
53
+ const parents = new Set();
54
+ const ancestors = new Map();
55
+ for (const track of tracks) {
56
+ const parentIds = [];
57
+ let { parent } = track.sequence;
58
+ while (parent !== null && !parentIds.includes(parent)) {
59
+ parentIds.push(parent);
60
+ parents.add(parent);
61
+ parent = (_c = (_a = byId.get(parent)) === null || _a === void 0 ? void 0 : _a.parent) !== null && _c !== void 0 ? _c : null;
62
+ }
63
+ ancestors.set(track.sequence.id, parentIds);
64
+ // Source identity survives remounts. For layers without source metadata,
65
+ // use the structural position instead of the ephemeral sequence ID.
66
+ const identity = track.nodePathInfo
67
+ ? ['source', (0, timeline_node_path_key_1.timelineNodePathInfoToKey)(track.nodePathInfo)]
68
+ : [
69
+ 'position',
70
+ ...[...parentIds]
71
+ .reverse()
72
+ .concat(track.sequence.id)
73
+ .map((id) => siblingIndices.get(id)),
74
+ ];
75
+ keys.set(track.sequence.id, JSON.stringify([compositionId, identity]));
76
+ }
77
+ return { keys, parents, ancestors };
78
+ }, [compositionId, sequences, tracks]);
79
+ const visibleTracks = (0, react_1.useMemo)(() => tracks.filter((track) => {
80
+ var _a;
81
+ return !((_a = hierarchy.ancestors.get(track.sequence.id)) !== null && _a !== void 0 ? _a : []).some((id) => {
82
+ const key = hierarchy.keys.get(id);
83
+ return key !== undefined && collapsed[key];
84
+ });
85
+ }), [hierarchy, collapsed, tracks]);
86
+ const value = (0, react_1.useMemo)(() => ({
87
+ collapsed,
88
+ keys: hierarchy.keys,
89
+ parents: hierarchy.parents,
90
+ toggle,
91
+ }), [collapsed, hierarchy, toggle]);
92
+ return { visibleTracks, value };
93
+ };
94
+ exports.useTimelineLayerChildren = useTimelineLayerChildren;
95
+ const TimelineLayerChildrenToggle = ({ sequence }) => {
96
+ const context = (0, react_1.useContext)(TimelineLayerChildrenContext);
97
+ const key = context === null || context === void 0 ? void 0 : context.keys.get(sequence.id);
98
+ const isCollapsed = key !== undefined && Boolean(context === null || context === void 0 ? void 0 : context.collapsed[key]);
99
+ const onClick = (0, react_1.useCallback)((event) => {
100
+ event.stopPropagation();
101
+ if (key !== undefined) {
102
+ context === null || context === void 0 ? void 0 : context.toggle(key);
103
+ }
104
+ }, [context, key]);
105
+ const stopPropagation = (0, react_1.useCallback)((event) => event.stopPropagation(), []);
106
+ if (!(context === null || context === void 0 ? void 0 : context.parents.has(sequence.id)) || key === undefined) {
107
+ return jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowSpacer, {});
108
+ }
109
+ const label = `${isCollapsed ? 'Expand' : 'Collapse'} children of ${sequence.displayName}`;
110
+ return (jsx_runtime_1.jsx("button", { type: "button", className: `${hoverable_1.HOVERABLE_CLASS_NAME} ${hoverable_1.FOCUS_VISIBLE_ONLY_CLASS_NAME}`, "aria-label": label, "aria-expanded": !isCollapsed, title: label, onClick: onClick, onPointerDown: stopPropagation, onDoubleClick: stopPropagation, style: {
111
+ ...(0, hoverable_1.hoverableStyle)({
112
+ idleBackground: colors_1.TRANSPARENT,
113
+ hoverBackground: colors_1.TRANSPARENT,
114
+ idleColor: colors_1.LIGHT_TEXT,
115
+ hoverColor: colors_1.WHITE,
116
+ }),
117
+ border: 'none',
118
+ padding: 0,
119
+ cursor: 'default',
120
+ display: 'flex',
121
+ alignItems: 'center',
122
+ justifyContent: 'center',
123
+ width: 12,
124
+ height: 16,
125
+ marginRight: 0,
126
+ flexShrink: 0,
127
+ }, children: jsx_runtime_1.jsx(TimelineCollapseToggle_1.TimelineCollapseToggle, { collapsed: isCollapsed, color: "currentColor" }) }));
128
+ };
129
+ exports.TimelineLayerChildrenToggle = TimelineLayerChildrenToggle;
@@ -35,8 +35,12 @@ const TimelineNumberField = ({ field, effectiveValue, onSave, onDragValueChange,
35
35
  }
36
36
  }, [onSave, propStatus]);
37
37
  const configuredStep = field.fieldSchema.type === 'number' ? field.fieldSchema.step : undefined;
38
- const step = configuredStep !== null && configuredStep !== void 0 ? configuredStep : 1;
39
- const allowStepMismatch = field.group === 'crop' ||
38
+ const currentValue = dragValue !== null && dragValue !== void 0 ? dragValue : effectiveValue;
39
+ const step = field.fieldSchema.type === 'font-weight' && currentValue % 100 === 0
40
+ ? 100
41
+ : (configuredStep !== null && configuredStep !== void 0 ? configuredStep : 1);
42
+ const allowStepMismatch = field.fieldSchema.type === 'font-weight' ||
43
+ field.group === 'crop' ||
40
44
  ('kind' in field && field.kind === 'effect-field');
41
45
  const formatter = (0, react_1.useCallback)((v) => {
42
46
  return (0, timeline_field_display_utils_1.formatTimelineFieldValueForDisplay)({
@@ -44,10 +48,14 @@ const TimelineNumberField = ({ field, effectiveValue, onSave, onDragValueChange,
44
48
  value: v,
45
49
  });
46
50
  }, [field.fieldSchema]);
47
- return (jsx_runtime_1.jsx(InputDragger_1.InputDragger, { type: "number", value: dragValue !== null && dragValue !== void 0 ? dragValue : effectiveValue, buttonStyle: timeline_field_utils_1.leftAlignedDraggerStyle, style: timeline_field_utils_1.draggerStyle, status: "ok", small: true, onValueChange: onValueChange, onValueChangeEnd: onValueChangeEnd, onTextChange: onTextChange, min: field.fieldSchema.type === 'number'
51
+ return (jsx_runtime_1.jsx(InputDragger_1.InputDragger, { type: "number", value: currentValue, buttonStyle: timeline_field_utils_1.leftAlignedDraggerStyle, style: timeline_field_utils_1.draggerStyle, status: "ok", small: true, onValueChange: onValueChange, onValueChangeEnd: onValueChangeEnd, onTextChange: onTextChange, min: field.fieldSchema.type === 'number'
48
52
  ? ((_a = field.fieldSchema.min) !== null && _a !== void 0 ? _a : -Infinity)
49
- : -Infinity, max: field.fieldSchema.type === 'number'
53
+ : field.fieldSchema.type === 'font-weight'
54
+ ? 1
55
+ : -Infinity, max: field.fieldSchema.type === 'number'
50
56
  ? ((_b = field.fieldSchema.max) !== null && _b !== void 0 ? _b : Infinity)
51
- : Infinity, step: step, formatter: formatter, rightAlign: false, allowStepMismatch: allowStepMismatch }));
57
+ : field.fieldSchema.type === 'font-weight'
58
+ ? 1000
59
+ : Infinity, step: step, dragSensitivity: field.fieldSchema.type === 'font-weight' && step === 100 ? 0.1 : 1, formatter: formatter, rightAlign: false, allowStepMismatch: allowStepMismatch }));
52
60
  };
53
61
  exports.TimelineNumberField = TimelineNumberField;
@@ -18,7 +18,6 @@ const ZOOM_WHEEL_SENSITIVITY = 0.06;
18
18
  const TimelinePinchZoom = () => {
19
19
  const isVideoComposition = (0, is_current_selected_still_1.useIsVideoComposition)();
20
20
  const videoConfig = remotion_1.Internals.useUnsafeVideoConfig();
21
- const { canvasContent } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
22
21
  const { zoom, setZoom } = (0, react_1.useContext)(timeline_zoom_1.TimelineZoomCtx);
23
22
  const { editorZoomGestures } = (0, react_1.useContext)(editor_zoom_gestures_1.EditorZoomGesturesContext);
24
23
  const zoomRef = (0, react_1.useRef)(zoom);
@@ -51,9 +50,6 @@ const TimelinePinchZoom = () => {
51
50
  if (!videoConfig || videoConfig.durationInFrames < 2) {
52
51
  return;
53
52
  }
54
- if (!canvasContent || canvasContent.type !== 'composition') {
55
- return;
56
- }
57
53
  const scrollEl = timeline_refs_1.scrollableRef.current;
58
54
  if (!scrollEl) {
59
55
  return;
@@ -70,14 +66,8 @@ const TimelinePinchZoom = () => {
70
66
  else if (deltaMode === WheelEvent.DOM_DELTA_PAGE) {
71
67
  scaledDeltaY *= scrollEl.clientHeight;
72
68
  }
73
- setZoom(canvasContent.compositionId, (z) => z * Math.exp(-scaledDeltaY * ZOOM_WHEEL_SENSITIVITY), { anchorFrame: null, anchorContentX });
74
- }, [
75
- editorZoomGestures,
76
- isVideoComposition,
77
- videoConfig,
78
- canvasContent,
79
- setZoom,
80
- ]);
69
+ setZoom(videoConfig.id, (z) => z * Math.exp(-scaledDeltaY * ZOOM_WHEEL_SENSITIVITY), { anchorFrame: null, anchorContentX });
70
+ }, [editorZoomGestures, isVideoComposition, videoConfig, setZoom]);
81
71
  const supportsWebKitPinch = typeof window !== 'undefined' && 'GestureEvent' in window;
82
72
  (0, react_1.useEffect)(() => {
83
73
  const el = timeline_refs_1.timelineVerticalScroll.current;
@@ -106,16 +96,13 @@ const TimelinePinchZoom = () => {
106
96
  if (!videoConfig || videoConfig.durationInFrames < 2) {
107
97
  return;
108
98
  }
109
- if (!canvasContent || canvasContent.type !== 'composition') {
110
- return;
111
- }
112
99
  const scrollEl = timeline_refs_1.scrollableRef.current;
113
100
  if (!scrollEl) {
114
101
  return;
115
102
  }
116
103
  e.preventDefault();
117
104
  suppressWheelFromWebKitPinchRef.current = true;
118
- pinchBaseZoomRef.current = getCurrentTimelineZoom(canvasContent.compositionId);
105
+ pinchBaseZoomRef.current = getCurrentTimelineZoom(videoConfig.id);
119
106
  };
120
107
  const onGestureChange = (event) => {
121
108
  const e = event;
@@ -126,9 +113,6 @@ const TimelinePinchZoom = () => {
126
113
  videoConfig.durationInFrames < 2) {
127
114
  return;
128
115
  }
129
- if (!canvasContent || canvasContent.type !== 'composition') {
130
- return;
131
- }
132
116
  const scrollEl = timeline_refs_1.scrollableRef.current;
133
117
  if (!scrollEl) {
134
118
  return;
@@ -138,7 +122,7 @@ const TimelinePinchZoom = () => {
138
122
  clientX: e.clientX,
139
123
  scrollEl,
140
124
  });
141
- setZoom(canvasContent.compositionId, () => base * e.scale, {
125
+ setZoom(videoConfig.id, () => base * e.scale, {
142
126
  anchorFrame: null,
143
127
  anchorContentX,
144
128
  });
@@ -161,7 +145,6 @@ const TimelinePinchZoom = () => {
161
145
  supportsWebKitPinch,
162
146
  isVideoComposition,
163
147
  videoConfig,
164
- canvasContent,
165
148
  getCurrentTimelineZoom,
166
149
  setZoom,
167
150
  ]);
@@ -180,9 +163,6 @@ const TimelinePinchZoom = () => {
180
163
  videoConfig.durationInFrames < 2) {
181
164
  return;
182
165
  }
183
- if (!canvasContent || canvasContent.type !== 'composition') {
184
- return;
185
- }
186
166
  const [t0, t1] = [event.touches[0], event.touches[1]];
187
167
  const initialDistance = Math.hypot(t1.clientX - t0.clientX, t1.clientY - t0.clientY);
188
168
  if (initialDistance < 1e-6) {
@@ -190,7 +170,7 @@ const TimelinePinchZoom = () => {
190
170
  }
191
171
  touchPinchRef.current = {
192
172
  initialDistance,
193
- initialZoom: getCurrentTimelineZoom(canvasContent.compositionId),
173
+ initialZoom: getCurrentTimelineZoom(videoConfig.id),
194
174
  };
195
175
  };
196
176
  const onTouchMove = (event) => {
@@ -201,9 +181,6 @@ const TimelinePinchZoom = () => {
201
181
  videoConfig.durationInFrames < 2) {
202
182
  return;
203
183
  }
204
- if (!canvasContent || canvasContent.type !== 'composition') {
205
- return;
206
- }
207
184
  const scrollEl = timeline_refs_1.scrollableRef.current;
208
185
  if (!scrollEl) {
209
186
  return;
@@ -217,7 +194,7 @@ const TimelinePinchZoom = () => {
217
194
  clientX,
218
195
  scrollEl,
219
196
  });
220
- setZoom(canvasContent.compositionId, () => pinch.initialZoom * ratio, {
197
+ setZoom(videoConfig.id, () => pinch.initialZoom * ratio, {
221
198
  anchorFrame: null,
222
199
  anchorContentX,
223
200
  });
@@ -241,7 +218,6 @@ const TimelinePinchZoom = () => {
241
218
  editorZoomGestures,
242
219
  isVideoComposition,
243
220
  videoConfig,
244
- canvasContent,
245
221
  getCurrentTimelineZoom,
246
222
  setZoom,
247
223
  ]);
@@ -16,17 +16,11 @@ const TimelinePlayCursorSyncer = () => {
16
16
  const timelinePosition = remotion_1.Internals.Timeline.useTimelinePosition();
17
17
  const playing = remotion_1.Internals.usePlaying();
18
18
  const { playbackRate } = remotion_1.Internals.usePlaybackRate();
19
- const { canvasContent } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
20
19
  const { zoom: zoomMap } = (0, react_1.useContext)(timeline_zoom_1.TimelineZoomCtx);
21
- const compositionId = canvasContent && canvasContent.type === 'composition'
22
- ? canvasContent.compositionId
23
- : null;
24
- // Asset previews have a synthetic video config, but no composition ID
25
- // with which to look up a persisted timeline zoom.
26
20
  const zoom = (0, get_timeline_max_zoom_1.getTimelineZoom)({
27
21
  durationInFrames: (_b = video === null || video === void 0 ? void 0 : video.durationInFrames) !== null && _b !== void 0 ? _b : 1,
28
22
  timelineViewportWidth: (_c = (_a = timeline_refs_1.scrollableRef.current) === null || _a === void 0 ? void 0 : _a.clientWidth) !== null && _c !== void 0 ? _c : 0,
29
- zoom: compositionId ? ((_d = zoomMap[compositionId]) !== null && _d !== void 0 ? _d : null) : null,
23
+ zoom: video ? ((_d = zoomMap[video.id]) !== null && _d !== void 0 ? _d : null) : null,
30
24
  });
31
25
  if (video) {
32
26
  (0, imperative_state_1.setCurrentFrame)(timelinePosition);
@@ -7,6 +7,7 @@ const TimelineBooleanField_1 = require("./TimelineBooleanField");
7
7
  const TimelineColorField_1 = require("./TimelineColorField");
8
8
  const TimelineEnumField_1 = require("./TimelineEnumField");
9
9
  const TimelineFontFamilyField_1 = require("./TimelineFontFamilyField");
10
+ const TimelineFontWeightField_1 = require("./TimelineFontWeightField");
10
11
  const TimelineNumberField_1 = require("./TimelineNumberField");
11
12
  const TimelineRotationField_1 = require("./TimelineRotationField");
12
13
  const TimelineScaleField_1 = require("./TimelineScaleField");
@@ -67,6 +68,9 @@ const TimelinePrimitiveFieldValue = ({ field, onSave, onDragValueChange, onDragE
67
68
  if (field.typeName === 'font-family') {
68
69
  return (jsx_runtime_1.jsx("span", { style: inlineWrapper, children: jsx_runtime_1.jsx(TimelineFontFamilyField_1.TimelineFontFamilyField, { effectiveValue: effectiveValue, field: field, onDragEnd: onDragEnd, onDragValueChange: onDragValueChange, onSave: onSave, propStatus: propStatus }) }));
69
70
  }
71
+ if (field.typeName === 'font-weight') {
72
+ return (jsx_runtime_1.jsx("span", { style: inlineWrapper, children: jsx_runtime_1.jsx(TimelineFontWeightField_1.TimelineFontWeightField, { effectiveValue: effectiveValue, field: field, onDragEnd: onDragEnd, onDragValueChange: onDragValueChange, onSave: onSave, propStatus: propStatus }) }));
73
+ }
70
74
  if (field.typeName === 'asset') {
71
75
  return (jsx_runtime_1.jsx("span", { style: assetInlineWrapper, children: jsx_runtime_1.jsx(TimelineAssetField_1.TimelineAssetField, { effectiveValue: effectiveValue, field: field, onDragEnd: onDragEnd, onDragValueChange: onDragValueChange, onSave: onSave, propStatus: propStatus }) }));
72
76
  }
@@ -35,6 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.TimelineSequence = void 0;
37
37
  const jsx_runtime_1 = require("react/jsx-runtime");
38
+ const canvas_1 = require("@remotion/canvas");
38
39
  const react_1 = __importStar(require("react"));
39
40
  const remotion_1 = require("remotion");
40
41
  const client_id_1 = require("../../helpers/client-id");
@@ -45,7 +46,7 @@ const get_timeline_sequence_layout_1 = require("../../helpers/get-timeline-seque
45
46
  const interactivity_enabled_1 = require("../../helpers/interactivity-enabled");
46
47
  const is_video_with_last_frame_hold_1 = require("../../helpers/is-video-with-last-frame-hold");
47
48
  const timeline_layout_1 = require("../../helpers/timeline-layout");
48
- const use_max_media_duration_1 = require("../../helpers/use-max-media-duration");
49
+ const use_media_metadata_1 = require("../../helpers/use-media-metadata");
49
50
  const modals_1 = require("../../state/modals");
50
51
  const AudioWaveform_1 = require("../AudioWaveform");
51
52
  const ConfirmationDialog_1 = require("../ConfirmationDialog");
@@ -55,6 +56,8 @@ const use_select_asset_1 = require("../use-select-asset");
55
56
  const disable_sequence_interactivity_1 = require("./disable-sequence-interactivity");
56
57
  const duplicate_selected_timeline_item_1 = require("./duplicate-selected-timeline-item");
57
58
  const get_sequence_context_menu_items_1 = require("./get-sequence-context-menu-items");
59
+ const get_sequence_split_menu_item_1 = require("./get-sequence-split-menu-item");
60
+ const get_timeline_media_start_frame_1 = require("./get-timeline-media-start-frame");
58
61
  const get_timeline_sequence_visible_layout_1 = require("./get-timeline-sequence-visible-layout");
59
62
  const imperative_state_1 = require("./imperative-state");
60
63
  const LoopedTimelineIndicators_1 = require("./LoopedTimelineIndicators");
@@ -115,7 +118,7 @@ const TimelineSequenceNegativeStartInner = ({ left, width, leftEdgeVisible, clip
115
118
  return (jsx_runtime_1.jsx("div", { style: outerStyle, children: jsx_runtime_1.jsx("div", { style: innerStyle }) }));
116
119
  };
117
120
  const TimelineSequenceNegativeStart = react_1.default.memo(TimelineSequenceNegativeStartInner);
118
- const TimelineSequenceCurrentFrame = ({ s, displayDurationInFrames, premount, postmount, negativeStart, leftEdgeVisible, negativeStartClipped, style, children, nodePathInfo, sequenceFrameOffset, fromCanUpdate, frozenFrame, onMoveDragPointerDown, onPointerDownCapture, onDoubleClick, }) => {
121
+ const TimelineSequenceCurrentFrame = ({ s, displayDurationInFrames, premount, postmount, negativeStart, leftEdgeVisible, negativeStartClipped, style, children, edgeDragHandles, nodePathInfo, sequenceFrameOffset, fromCanUpdate, frozenFrame, onMoveDragPointerDown, onPointerDownCapture, onDoubleClick, }) => {
119
122
  var _a, _b, _c;
120
123
  const ref = (0, react_1.useRef)(null);
121
124
  const { onSelect, selectable, selected, selectionItem } = (0, TimelineSelection_1.useTimelineRowSelection)(nodePathInfo);
@@ -197,31 +200,36 @@ const TimelineSequenceCurrentFrame = ({ s, displayDurationInFrames, premount, po
197
200
  display: 'flex',
198
201
  alignItems: 'center',
199
202
  }, children: jsx_runtime_1.jsx(TimelineSequenceFrame_1.TimelineSequenceFrame, { premounted: isPremounting, postmounted: isPostmounting ? s.duration - 1 : null, roundedFrame: roundedFrame, frozenFrame: frozenFrame }) })) : null] }));
200
- return (jsx_runtime_1.jsx("div", { ref: ref, [TimelineSelection_1.TIMELINE_MARQUEE_ITEM_ATTR]: true, style: actualStyle, title: s.displayName, onPointerDownCapture: onPointerDownCapture, onPointerDown: selectable ? onPointerDown : undefined, onDoubleClick: onDoubleClick, children: negativeStart ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
201
- jsx_runtime_1.jsx(TimelineSequenceNegativeStart, { left: negativeStart.left, width: negativeStart.width, leftEdgeVisible: leftEdgeVisible, clipped: negativeStartClipped }), jsx_runtime_1.jsx("div", { style: {
202
- background: style.background,
203
- border: style.border,
204
- borderBottomLeftRadius: 0,
205
- borderBottomRightRadius: style.borderBottomRightRadius,
206
- borderLeft: 'none',
207
- borderRightColor: style.borderRightColor,
208
- borderTopLeftRadius: 0,
209
- borderTopRightRadius: style.borderTopRightRadius,
210
- boxSizing: 'border-box',
211
- height: '100%',
212
- left: negativeStartEnd,
213
- overflow: 'hidden',
214
- position: 'absolute',
215
- top: 0,
216
- width: `calc(100% - ${negativeStartEnd}px)`,
217
- }, children: jsx_runtime_1.jsx("div", { style: {
203
+ return (jsx_runtime_1.jsxs("div", { ref: ref, [TimelineSelection_1.TIMELINE_MARQUEE_ITEM_ATTR]: true, style: actualStyle, title: s.displayName, onPointerDownCapture: onPointerDownCapture, onPointerDown: selectable ? onPointerDown : undefined, onDoubleClick: onDoubleClick, children: [negativeStart ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
204
+ jsx_runtime_1.jsx(TimelineSequenceNegativeStart, { left: negativeStart.left, width: negativeStart.width, leftEdgeVisible: leftEdgeVisible, clipped: negativeStartClipped }), jsx_runtime_1.jsx("div", { style: {
205
+ background: style.background,
206
+ border: style.border,
207
+ borderBottomLeftRadius: 0,
208
+ borderBottomRightRadius: style.borderBottomRightRadius,
209
+ borderLeft: 'none',
210
+ borderRightColor: style.borderRightColor,
211
+ borderTopLeftRadius: 0,
212
+ borderTopRightRadius: style.borderTopRightRadius,
213
+ boxSizing: 'border-box',
218
214
  height: '100%',
219
- left: -negativeStartEnd,
215
+ left: negativeStartEnd,
216
+ overflow: 'hidden',
220
217
  position: 'absolute',
221
218
  top: 0,
222
- width: style.width,
223
- }, children: content }) })
224
- ] })) : (content) }));
219
+ width: `calc(100% - ${negativeStartEnd}px)`,
220
+ }, children: jsx_runtime_1.jsx("div", { style: {
221
+ height: '100%',
222
+ left: -negativeStartEnd,
223
+ position: 'absolute',
224
+ top: 0,
225
+ width: style.width,
226
+ }, children: content }) })
227
+ ] })) : (jsx_runtime_1.jsx("div", { style: {
228
+ position: 'absolute',
229
+ inset: 0,
230
+ overflow: 'hidden',
231
+ borderRadius: 'inherit',
232
+ }, children: content })), edgeDragHandles] }));
225
233
  };
226
234
  const TimelineSequenceInner = ({ s, connectedCompositions, windowWidth, nodePathInfo, sequenceFrameOffset, cascadedStart, localStart, }) => {
227
235
  // If a duration is 1, it is essentially a still and it should have width 0
@@ -230,11 +238,27 @@ const TimelineSequenceInner = ({ s, connectedCompositions, windowWidth, nodePath
230
238
  var _a, _b, _c;
231
239
  var _d, _e, _f, _g, _h, _j, _k;
232
240
  const video = remotion_1.Internals.useVideo();
241
+ const { sequences } = (0, react_1.useContext)(remotion_1.Internals.SequenceManager);
233
242
  const renderWindow = (0, react_1.useContext)(TimelineViewport_1.TimelineViewportContext);
234
243
  const dragAwareDoubleClick = (0, react_1.useMemo)(() => (0, drag_aware_double_click_1.createDragAwareDoubleClickTracker)(), []);
235
- 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);
236
- const effectiveMaxMediaDuration = s.loopDisplay ? null : maxMediaDuration;
244
+ const mediaMetadata = (0, use_media_metadata_1.useMediaMetadata)(s.type === 'audio' || s.type === 'video' ? s.src : null);
237
245
  const extendVideoLastFrame = (0, is_video_with_last_frame_hold_1.isVideoWithLastFrameHold)(s);
246
+ const naturalMediaDuration = (s.type === 'audio' || s.type === 'video') &&
247
+ mediaMetadata !== null &&
248
+ s.playbackRate > 0
249
+ ? Math.max(0, (mediaMetadata.duration * ((_d = video === null || video === void 0 ? void 0 : video.fps) !== null && _d !== void 0 ? _d : 30) -
250
+ (0, get_timeline_media_start_frame_1.getTimelineMediaStartFrame)({
251
+ startMediaFrom: s.startMediaFrom,
252
+ mediaFrameAtSequenceZero: s.mediaFrameAtSequenceZero,
253
+ sequenceFrameOffset,
254
+ playbackRate: s.playbackRate,
255
+ })) /
256
+ s.playbackRate)
257
+ : null;
258
+ const maxMediaDuration = s.type === 'sequence' || s.type === 'image' || extendVideoLastFrame
259
+ ? Infinity
260
+ : naturalMediaDuration;
261
+ const effectiveMaxMediaDuration = s.loopDisplay ? null : maxMediaDuration;
238
262
  const { canOpenInEditor, canConfigureApps, codingAgentInfo, editorInfo, openInCodingAgent, openInEditor, originalLocation, } = (0, use_open_sequence_in_apps_1.useOpenSequenceInApps)(s);
239
263
  const validatedLocation = (0, react_1.useMemo)(() => {
240
264
  var _a;
@@ -401,6 +425,14 @@ const TimelineSequenceInner = ({ s, connectedCompositions, windowWidth, nodePath
401
425
  onDuplicateSelectedSequences,
402
426
  });
403
427
  }
428
+ const splitMenuItem = (0, get_sequence_split_menu_item_1.getSequenceSplitMenuItem)({
429
+ nodePathInfo,
430
+ sequence: s,
431
+ propStatuses: propStatusesForOverride,
432
+ splitFrame: (0, imperative_state_1.getCurrentFrame)(),
433
+ canEditSource: previewInteractive && Boolean(validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source),
434
+ hasMultipleSelection: selected && selectedItems.length > 1,
435
+ });
404
436
  const freezeFrameMenuItem = (0, use_sequence_freeze_frame_menu_item_1.getSequenceFreezeFrameMenuItem)({
405
437
  clientId: previewInteractive && previewServerState.type === 'connected'
406
438
  ? previewServerState.clientId
@@ -442,8 +474,11 @@ const TimelineSequenceInner = ({ s, connectedCompositions, windowWidth, nodePath
442
474
  originalLocation,
443
475
  selectAsset,
444
476
  sequence: s,
445
- sourceActions: (0, interactivity_enabled_1.isStudioInteractivityEnabled)() && freezeFrameMenuItem
446
- ? [freezeFrameMenuItem]
477
+ sourceActions: (0, interactivity_enabled_1.isStudioInteractivityEnabled)()
478
+ ? [
479
+ ...(splitMenuItem ? [splitMenuItem] : []),
480
+ ...(freezeFrameMenuItem ? [freezeFrameMenuItem] : []),
481
+ ]
447
482
  : [],
448
483
  });
449
484
  }, [
@@ -457,6 +492,7 @@ const TimelineSequenceInner = ({ s, connectedCompositions, windowWidth, nodePath
457
492
  isProgrammaticallyDuplicated,
458
493
  mediaSrc,
459
494
  nodePath,
495
+ nodePathInfo,
460
496
  onSelect,
461
497
  onDeleteSequenceFromSource,
462
498
  onDeleteSelectedSequences,
@@ -473,6 +509,7 @@ const TimelineSequenceInner = ({ s, connectedCompositions, windowWidth, nodePath
473
509
  selectAsset,
474
510
  selectable,
475
511
  selected,
512
+ selectedItems.length,
476
513
  selectedSequenceNodePathInfos,
477
514
  sequenceFrameOffset,
478
515
  setPropStatuses,
@@ -497,7 +534,8 @@ const TimelineSequenceInner = ({ s, connectedCompositions, windowWidth, nodePath
497
534
  durationInFrames: displayDurationInFrames,
498
535
  startFrom: s.loopDisplay ? s.from + s.loopDisplay.startOffset : s.from,
499
536
  cascadedStart,
500
- startFromMedia: s.type === 'sequence' || s.type === 'image' ? 0 : s.startMediaFrom,
537
+ // The media duration cap already accounts for trimming and playback speed.
538
+ startFromMedia: 0,
501
539
  maxMediaDuration: effectiveMaxMediaDuration,
502
540
  video,
503
541
  windowWidth,
@@ -544,7 +582,33 @@ const TimelineSequenceInner = ({ s, connectedCompositions, windowWidth, nodePath
544
582
  }, [visibleLayout]);
545
583
  const showLeftBorderRadius = (visibleLayout === null || visibleLayout === void 0 ? void 0 : visibleLayout.leftEdgeVisible) === true &&
546
584
  localStart >= 0 &&
547
- ((_h = s.trimBefore) !== null && _h !== void 0 ? _h : 0) === 0;
585
+ ((_h = s.trimBefore) !== null && _h !== void 0 ? _h : 0) === 0 &&
586
+ (s.type === 'sequence' ||
587
+ s.type === 'image' ||
588
+ (0, get_timeline_media_start_frame_1.getTimelineMediaStartFrame)({
589
+ startMediaFrom: s.startMediaFrom,
590
+ mediaFrameAtSequenceZero: s.mediaFrameAtSequenceZero,
591
+ sequenceFrameOffset,
592
+ playbackRate: s.playbackRate,
593
+ }) === 0);
594
+ // Compare frame boundaries: fractional media durations still occupy the last frame.
595
+ const endsAtNaturalMediaDuration = !s.loopDisplay &&
596
+ s.frozenFrame === null &&
597
+ (s.type === 'audio' || s.type === 'video') &&
598
+ s.frozenMediaFrame === null &&
599
+ naturalMediaDuration !== null &&
600
+ Number.isFinite(naturalMediaDuration) &&
601
+ naturalMediaDuration > 0 &&
602
+ Math.ceil(Math.min(s.duration, video.durationInFrames - s.from, maxMediaDuration !== null && maxMediaDuration !== void 0 ? maxMediaDuration : Infinity)) === Math.ceil(naturalMediaDuration);
603
+ const parentSequence = sequences.find((candidate) => candidate.id === s.parent);
604
+ const parentEnd = parentSequence
605
+ ? (0, canvas_1.getTimelineVisibleStart)(parentSequence, sequences) +
606
+ (0, canvas_1.getTimelineVisibleDuration)(parentSequence, sequences)
607
+ : video.durationInFrames;
608
+ const endsAtContainerBoundary = Math.ceil(s.from + displayDurationInFrames) >=
609
+ Math.ceil(Math.min(parentEnd, video.durationInFrames));
610
+ const showRightBorderRadius = (visibleLayout === null || visibleLayout === void 0 ? void 0 : visibleLayout.rightEdgeVisible) === true &&
611
+ (endsAtContainerBoundary || endsAtNaturalMediaDuration);
548
612
  const style = (0, react_1.useMemo)(() => {
549
613
  var _a, _b;
550
614
  return {
@@ -562,16 +626,23 @@ const TimelineSequenceInner = ({ s, connectedCompositions, windowWidth, nodePath
562
626
  : colors_1.TRANSPARENT,
563
627
  borderTopLeftRadius: showLeftBorderRadius ? 2 : 0,
564
628
  borderBottomLeftRadius: showLeftBorderRadius ? 2 : 0,
565
- borderTopRightRadius: (visibleLayout === null || visibleLayout === void 0 ? void 0 : visibleLayout.rightEdgeVisible) ? 2 : 0,
566
- borderBottomRightRadius: (visibleLayout === null || visibleLayout === void 0 ? void 0 : visibleLayout.rightEdgeVisible) ? 2 : 0,
629
+ borderTopRightRadius: showRightBorderRadius ? 2 : 0,
630
+ borderBottomRightRadius: showRightBorderRadius ? 2 : 0,
567
631
  position: 'absolute',
568
632
  height: (0, timeline_layout_1.getTimelineLayerHeight)(s.type),
569
633
  marginLeft: (_a = visibleLayout === null || visibleLayout === void 0 ? void 0 : visibleLayout.marginLeft) !== null && _a !== void 0 ? _a : 0,
570
634
  width: (_b = visibleLayout === null || visibleLayout === void 0 ? void 0 : visibleLayout.width) !== null && _b !== void 0 ? _b : 0,
571
635
  color: colors_1.WHITE,
572
- overflow: 'hidden',
636
+ // Edge handles extend outside the layer; media is clipped separately.
637
+ overflow: 'visible',
573
638
  };
574
- }, [negativeStartClipped, s.type, showLeftBorderRadius, visibleLayout]);
639
+ }, [
640
+ negativeStartClipped,
641
+ s.type,
642
+ showLeftBorderRadius,
643
+ showRightBorderRadius,
644
+ visibleLayout,
645
+ ]);
575
646
  const showRightEdgeDragHandle = (0, TimelineSequenceRightEdgeDragHandle_1.isTimelineSequenceDurationDraggable)(s) &&
576
647
  nodePath !== null &&
577
648
  validatedLocation !== null &&
@@ -592,14 +663,14 @@ const TimelineSequenceInner = ({ s, connectedCompositions, windowWidth, nodePath
592
663
  const mediaDisplayDurationInFrames = visibleLayout.media
593
664
  ? visibleLayout.media.width / frameIncrement
594
665
  : 0;
595
- const sequence = (jsx_runtime_1.jsxs(TimelineSequenceCurrentFrame, { s: s, displayDurationInFrames: displayDurationInFrames, premount: visibleLayout.premount, postmount: visibleLayout.postmount, negativeStart: visibleLayout.negativeStart, leftEdgeVisible: visibleLayout.leftEdgeVisible, negativeStartClipped: negativeStartClipped, style: style, nodePathInfo: nodePathInfo, sequenceFrameOffset: sequenceFrameOffset, fromCanUpdate: fromCanUpdate, frozenFrame: frozenFrame, onMoveDragPointerDown: onMoveDragPointerDown, onPointerDownCapture: dragAwareDoubleClick.beginPointerGesture, onDoubleClick: canHandleSequenceDoubleClick ? onSequenceDoubleClick : undefined, children: [s.type === 'audio' && visibleLayout.media ? (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, muted: s.muted, visualizationWidth: visibleLayout.media.width, startFrom: s.startMediaFrom, durationInFrames: s.duration, displayOffsetInFrames: mediaDisplayOffsetInFrames, displayDurationInFrames: mediaDisplayDurationInFrames, volume: s.volume, playbackRate: s.playbackRate, loopDisplay: s.loopDisplay }) })) : null, s.type === 'video' && visibleLayout.media ? (jsx_runtime_1.jsx(TimelineVideoInfo_1.TimelineVideoInfo, { src: s.src, visualizationWidth: visibleLayout.media.width, displayOffsetInFrames: mediaDisplayOffsetInFrames, displayDurationInFrames: mediaDisplayDurationInFrames, startMediaFrom: s.startMediaFrom, mediaFrameAtSequenceZero: s.mediaFrameAtSequenceZero, sequenceFrameOffset: sequenceFrameOffset, playbackRate: s.playbackRate, volume: s.volume, muted: s.muted, doesVolumeChange: s.doesVolumeChange, marginLeft: visibleLayout.media.left, loopDisplay: s.loopDisplay, frozenMediaFrame: s.frozenMediaFrame, extendLastFrame: extendVideoLastFrame })) : null, s.type === 'image' && visibleLayout.media ? (jsx_runtime_1.jsx("div", { style: mediaVisualizationStyle, children: jsx_runtime_1.jsx(TimelineImageInfo_1.TimelineImageInfo, { src: s.src, offsetInPixels: visibleLayout.media.offset }) })) : null, s.loopDisplay === undefined ? null : (jsx_runtime_1.jsx(LoopedTimelineIndicators_1.LoopedTimelineIndicator, { loops: s.loopDisplay.numberOfTimes, fullWidth: width, visibleOffset: visibleLayout.cropLeft, visibleWidth: visibleLayout.width })), showLeftEdgeDragHandle &&
596
- visibleLayout.leftEdgeVisible &&
597
- negativeStartWidth === 0 &&
598
- nodePathInfo &&
599
- validatedLocation ? (jsx_runtime_1.jsx(TimelineSequenceRightEdgeDragHandle_1.TimelineSequenceLeftEdgeDragHandle, { nodePathInfo: nodePathInfo, windowWidth: windowWidth, timelineDurationInFrames: (_j = video.durationInFrames) !== null && _j !== void 0 ? _j : 1, onDragEnd: dragAwareDoubleClick.endPointerGesture })) : null, showRightEdgeDragHandle &&
600
- visibleLayout.rightEdgeVisible &&
601
- nodePathInfo &&
602
- validatedLocation ? (jsx_runtime_1.jsx(TimelineSequenceRightEdgeDragHandle_1.TimelineSequenceRightEdgeDragHandle, { nodePathInfo: nodePathInfo, windowWidth: windowWidth, timelineDurationInFrames: (_k = video.durationInFrames) !== null && _k !== void 0 ? _k : 1, onDragEnd: dragAwareDoubleClick.endPointerGesture })) : null] }));
666
+ const sequence = (jsx_runtime_1.jsxs(TimelineSequenceCurrentFrame, { s: s, displayDurationInFrames: displayDurationInFrames, premount: visibleLayout.premount, postmount: visibleLayout.postmount, negativeStart: visibleLayout.negativeStart, leftEdgeVisible: visibleLayout.leftEdgeVisible, negativeStartClipped: negativeStartClipped, style: style, nodePathInfo: nodePathInfo, sequenceFrameOffset: sequenceFrameOffset, fromCanUpdate: fromCanUpdate, frozenFrame: frozenFrame, onMoveDragPointerDown: onMoveDragPointerDown, onPointerDownCapture: dragAwareDoubleClick.beginPointerGesture, edgeDragHandles: jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [showLeftEdgeDragHandle &&
667
+ visibleLayout.leftEdgeVisible &&
668
+ negativeStartWidth === 0 &&
669
+ nodePathInfo &&
670
+ validatedLocation ? (jsx_runtime_1.jsx(TimelineSequenceRightEdgeDragHandle_1.TimelineSequenceLeftEdgeDragHandle, { nodePathInfo: nodePathInfo, windowWidth: windowWidth, timelineDurationInFrames: (_j = video.durationInFrames) !== null && _j !== void 0 ? _j : 1, onDragEnd: dragAwareDoubleClick.endPointerGesture, onSelect: onSelect, selected: selected })) : null, showRightEdgeDragHandle &&
671
+ visibleLayout.rightEdgeVisible &&
672
+ nodePathInfo &&
673
+ validatedLocation ? (jsx_runtime_1.jsx(TimelineSequenceRightEdgeDragHandle_1.TimelineSequenceRightEdgeDragHandle, { nodePathInfo: nodePathInfo, windowWidth: windowWidth, timelineDurationInFrames: (_k = video.durationInFrames) !== null && _k !== void 0 ? _k : 1, onDragEnd: dragAwareDoubleClick.endPointerGesture, onSelect: onSelect, selected: selected })) : null] }), onDoubleClick: canHandleSequenceDoubleClick ? onSequenceDoubleClick : undefined, children: [s.type === 'audio' && visibleLayout.media ? (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, muted: s.muted, visualizationWidth: visibleLayout.media.width, startFrom: s.startMediaFrom, durationInFrames: s.duration, displayOffsetInFrames: mediaDisplayOffsetInFrames, displayDurationInFrames: mediaDisplayDurationInFrames, volume: s.volume, playbackRate: s.playbackRate, loopDisplay: s.loopDisplay }) })) : null, s.type === 'video' && visibleLayout.media ? (jsx_runtime_1.jsx(TimelineVideoInfo_1.TimelineVideoInfo, { src: s.src, visualizationWidth: visibleLayout.media.width, displayOffsetInFrames: mediaDisplayOffsetInFrames, displayDurationInFrames: mediaDisplayDurationInFrames, startMediaFrom: s.startMediaFrom, mediaFrameAtSequenceZero: s.mediaFrameAtSequenceZero, sequenceFrameOffset: sequenceFrameOffset, playbackRate: s.playbackRate, volume: s.volume, muted: s.muted, doesVolumeChange: s.doesVolumeChange, marginLeft: visibleLayout.media.left, loopDisplay: s.loopDisplay, frozenMediaFrame: s.frozenMediaFrame, extendLastFrame: extendVideoLastFrame })) : null, s.type === 'image' && visibleLayout.media ? (jsx_runtime_1.jsx("div", { style: mediaVisualizationStyle, children: jsx_runtime_1.jsx(TimelineImageInfo_1.TimelineImageInfo, { src: s.src, offsetInPixels: visibleLayout.media.offset }) })) : null, s.loopDisplay === undefined ? null : (jsx_runtime_1.jsx(LoopedTimelineIndicators_1.LoopedTimelineIndicator, { loops: s.loopDisplay.numberOfTimes, fullWidth: width, visibleOffset: visibleLayout.cropLeft, visibleWidth: visibleLayout.width }))] }));
603
674
  return previewConnected || window.remotion_isReadOnlyStudio ? (jsx_runtime_1.jsx(ContextMenu_1.ContextMenu, { getItems: getContextMenuItems, children: sequence })) : (sequence);
604
675
  };
605
676
  exports.TimelineSequence = react_1.default.memo(TimelineSequenceFn);