@remotion/studio 4.0.513 → 4.0.514

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 (174) hide show
  1. package/dist/Studio.js +2 -1
  2. package/dist/components/AskAiModal.js +1 -1
  3. package/dist/components/AssetSelector.js +2 -0
  4. package/dist/components/AssetSelectorItem.js +1 -2
  5. package/dist/components/AudioWaveform.d.ts +3 -0
  6. package/dist/components/AudioWaveform.js +55 -67
  7. package/dist/components/Canvas.js +40 -5
  8. package/dist/components/CanvasOrLoading.js +5 -0
  9. package/dist/components/CompositionSelector.js +2 -0
  10. package/dist/components/ConfigureDefaultEditorModal.js +17 -11
  11. package/dist/components/Editor.js +16 -1
  12. package/dist/components/ElementInstallConfirmation.d.ts +1 -0
  13. package/dist/components/ElementInstallConfirmation.js +4 -2
  14. package/dist/components/FixComputedValueModal.d.ts +9 -0
  15. package/dist/components/FixComputedValueModal.js +217 -0
  16. package/dist/components/InitialCompositionLoader.js +19 -0
  17. package/dist/components/InlineDropdown.js +4 -4
  18. package/dist/components/InspectorInfoHeader.js +3 -3
  19. package/dist/components/InspectorOpenInEditor.js +3 -1
  20. package/dist/components/InspectorPanel/CompositionInspector.js +11 -1
  21. package/dist/components/InspectorPanel/CompositionInspectorHeader.js +2 -2
  22. package/dist/components/InspectorPanel/ConnectedCompositionsSection.js +1 -1
  23. package/dist/components/InspectorPanel/EasingInspector.js +1 -1
  24. package/dist/components/InspectorPanel/KeyframeInspector.js +2 -2
  25. package/dist/components/InspectorPanel/SequenceInspectorHeader.js +1 -1
  26. package/dist/components/InspectorPanel/SequenceSelectionInspector.js +35 -6
  27. package/dist/components/InspectorPanel/common.d.ts +5 -5
  28. package/dist/components/InspectorPanel/common.js +8 -8
  29. package/dist/components/InspectorPanel/styles.d.ts +1 -1
  30. package/dist/components/InspectorPanel/styles.js +4 -2
  31. package/dist/components/InspectorSourceLocation.d.ts +1 -1
  32. package/dist/components/InspectorSourceLocation.js +2 -2
  33. package/dist/components/LicenseKeyValidation.js +2 -2
  34. package/dist/components/Modals.js +2 -1
  35. package/dist/components/NewComposition/CodemodFooter.d.ts +1 -0
  36. package/dist/components/NewComposition/CodemodFooter.js +10 -8
  37. package/dist/components/NewComposition/DeleteComposition.js +1 -1
  38. package/dist/components/NewComposition/DeleteFolder.js +1 -1
  39. package/dist/components/NewComposition/DuplicateComposition.js +7 -2
  40. package/dist/components/NewComposition/NewComposition.js +1 -1
  41. package/dist/components/NewComposition/NewFolder.js +1 -1
  42. package/dist/components/NewComposition/RenameComposition.js +1 -1
  43. package/dist/components/NewComposition/RenameFolder.js +1 -1
  44. package/dist/components/NewComposition/duplicate-composition-api.d.ts +16 -0
  45. package/dist/components/NewComposition/duplicate-composition-api.js +16 -0
  46. package/dist/components/NoRegisterRoot.js +1 -1
  47. package/dist/components/QuickSwitcher/ExplorerQuickSwitcherTrigger.js +4 -3
  48. package/dist/components/QuickSwitcher/QuickSwitcherContent.js +1 -0
  49. package/dist/components/QuickSwitcher/fuzzy-search.js +1 -1
  50. package/dist/components/RefreshCompositionOverlay.js +1 -1
  51. package/dist/components/RenderButton.js +6 -3
  52. package/dist/components/RenderModal/WebRenderModal.js +6 -2
  53. package/dist/components/RenderModal/WebRenderModalAdvanced.d.ts +2 -0
  54. package/dist/components/RenderModal/WebRenderModalAdvanced.js +9 -2
  55. package/dist/components/RenderModal/render-modals.js +5 -1
  56. package/dist/components/RenderQueue/ClientRenderQueueProcessor.js +5 -1
  57. package/dist/components/RenderQueue/actions.js +12 -2
  58. package/dist/components/RenderQueue/client-side-render-types.d.ts +1 -0
  59. package/dist/components/RenderingSettings.d.ts +2 -0
  60. package/dist/components/RenderingSettings.js +355 -0
  61. package/dist/components/SelectedOutlineElement.js +3 -3
  62. package/dist/components/SelectedOutlinePolygon.d.ts +1 -0
  63. package/dist/components/SelectedOutlinePolygon.js +53 -9
  64. package/dist/components/SettingsContext.d.ts +4 -1
  65. package/dist/components/SettingsContext.js +9 -2
  66. package/dist/components/SettingsModal.d.ts +1 -1
  67. package/dist/components/SettingsModal.js +10 -1
  68. package/dist/components/SettingsModalFooter.js +1 -1
  69. package/dist/components/StudioSettings.d.ts +2 -0
  70. package/dist/components/StudioSettings.js +185 -0
  71. package/dist/components/Timeline/LoopedIndicator.js +1 -1
  72. package/dist/components/Timeline/LoopedTimelineIndicators.d.ts +3 -0
  73. package/dist/components/Timeline/LoopedTimelineIndicators.js +22 -14
  74. package/dist/components/Timeline/Timeline.js +11 -9
  75. package/dist/components/Timeline/TimelineAssetField.d.ts +2 -2
  76. package/dist/components/Timeline/TimelineAssetField.js +1 -1
  77. package/dist/components/Timeline/TimelineDragHandler.js +62 -76
  78. package/dist/components/Timeline/TimelineEffectItem.js +1 -1
  79. package/dist/components/Timeline/TimelineEffectPropItem.d.ts +4 -2
  80. package/dist/components/Timeline/TimelineEffectPropItem.js +16 -11
  81. package/dist/components/Timeline/TimelineExpandedRow.d.ts +1 -1
  82. package/dist/components/Timeline/TimelineExpandedRow.js +4 -4
  83. package/dist/components/Timeline/TimelineExpandedSection.js +1 -1
  84. package/dist/components/Timeline/TimelineHeightContainer.d.ts +0 -4
  85. package/dist/components/Timeline/TimelineHeightContainer.js +4 -4
  86. package/dist/components/Timeline/TimelineImageInfo.d.ts +1 -0
  87. package/dist/components/Timeline/TimelineImageInfo.js +3 -2
  88. package/dist/components/Timeline/TimelineKeyframeControls.js +6 -1
  89. package/dist/components/Timeline/TimelineList.d.ts +1 -5
  90. package/dist/components/Timeline/TimelineList.js +14 -9
  91. package/dist/components/Timeline/TimelinePinchZoom.js +5 -5
  92. package/dist/components/Timeline/TimelineRowChrome.d.ts +0 -2
  93. package/dist/components/Timeline/TimelineRowChrome.js +12 -5
  94. package/dist/components/Timeline/TimelineSchemaField.d.ts +7 -3
  95. package/dist/components/Timeline/TimelineSchemaField.js +71 -13
  96. package/dist/components/Timeline/TimelineScrollable.js +3 -1
  97. package/dist/components/Timeline/TimelineSelection.d.ts +5 -2
  98. package/dist/components/Timeline/TimelineSelection.js +90 -103
  99. package/dist/components/Timeline/TimelineSequence.js +59 -25
  100. package/dist/components/Timeline/TimelineSequenceItem.d.ts +1 -1
  101. package/dist/components/Timeline/TimelineSequenceItem.js +15 -9
  102. package/dist/components/Timeline/TimelineSequencePropItem.d.ts +2 -1
  103. package/dist/components/Timeline/TimelineSequencePropItem.js +3 -3
  104. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +33 -10
  105. package/dist/components/Timeline/TimelineSlider.js +42 -33
  106. package/dist/components/Timeline/TimelineTimeIndicators.js +90 -98
  107. package/dist/components/Timeline/TimelineTracks.d.ts +0 -2
  108. package/dist/components/Timeline/TimelineTracks.js +11 -4
  109. package/dist/components/Timeline/TimelineTransformOriginField.js +1 -1
  110. package/dist/components/Timeline/TimelineVideoInfo.d.ts +4 -4
  111. package/dist/components/Timeline/TimelineVideoInfo.js +151 -61
  112. package/dist/components/Timeline/TimelineViewport.d.ts +12 -0
  113. package/dist/components/Timeline/TimelineViewport.js +62 -0
  114. package/dist/components/Timeline/TimelineVirtualization.d.ts +22 -0
  115. package/dist/components/Timeline/TimelineVirtualization.js +144 -0
  116. package/dist/components/Timeline/TimelineZoomControls.js +16 -8
  117. package/dist/components/Timeline/call-add-keyframe.js +31 -3
  118. package/dist/components/Timeline/call-delete-keyframe.js +13 -3
  119. package/dist/components/Timeline/call-move-keyframe.js +11 -1
  120. package/dist/components/Timeline/call-update-keyframe-settings.js +31 -3
  121. package/dist/components/Timeline/delete-selected-timeline-item.js +2 -1
  122. package/dist/components/Timeline/get-timeline-keyframes.d.ts +1 -2
  123. package/dist/components/Timeline/get-timeline-keyframes.js +1 -8
  124. package/dist/components/Timeline/get-timeline-sequence-visible-layout.d.ts +30 -0
  125. package/dist/components/Timeline/get-timeline-sequence-visible-layout.js +61 -0
  126. package/dist/components/Timeline/split-selected-timeline-item.js +2 -2
  127. package/dist/components/Timeline/timeline-scroll-logic.d.ts +24 -0
  128. package/dist/components/Timeline/timeline-scroll-logic.js +127 -4
  129. package/dist/components/Timeline/use-timeline-height.d.ts +3 -5
  130. package/dist/components/Timeline/use-timeline-height.js +16 -18
  131. package/dist/components/UpdateCheck.d.ts +2 -10
  132. package/dist/components/UpdateCheck.js +8 -2
  133. package/dist/components/VisualControls/VisualControlHandle.js +8 -0
  134. package/dist/components/delete-jsx-node-api.d.ts +2 -0
  135. package/dist/components/delete-jsx-node-api.js +12 -0
  136. package/dist/components/element-install-api.d.ts +3 -0
  137. package/dist/components/element-install-api.js +19 -0
  138. package/dist/components/import-assets.js +20 -9
  139. package/dist/components/reorder-sequence-api.d.ts +2 -0
  140. package/dist/components/reorder-sequence-api.js +12 -0
  141. package/dist/components/split-jsx-sequence-api.d.ts +2 -0
  142. package/dist/components/split-jsx-sequence-api.js +12 -0
  143. package/dist/components/split-video-from-audio-api.d.ts +2 -0
  144. package/dist/components/split-video-from-audio-api.js +12 -0
  145. package/dist/error-overlay/remotion-overlay/Overlay.js +1 -1
  146. package/dist/esm/{chunk-tv7r0jy3.js → chunk-xn2q7eem.js} +11073 -7495
  147. package/dist/esm/index.mjs +7 -5
  148. package/dist/esm/internals.mjs +11073 -7495
  149. package/dist/esm/previewEntry.mjs +10905 -7327
  150. package/dist/esm/renderEntry.mjs +2 -3
  151. package/dist/helpers/browser-studio-operations.d.ts +2 -0
  152. package/dist/helpers/browser-studio-operations.js +10 -1
  153. package/dist/helpers/get-timeline-max-zoom.d.ts +26 -0
  154. package/dist/helpers/get-timeline-max-zoom.js +45 -0
  155. package/dist/helpers/inject-css.js +2 -2
  156. package/dist/helpers/render-codec-label.d.ts +1 -1
  157. package/dist/helpers/retry-payload.js +1 -0
  158. package/dist/helpers/studio-runtime-config.d.ts +1 -1
  159. package/dist/helpers/studio-runtime-config.js +2 -3
  160. package/dist/helpers/timeline-layout.d.ts +3 -1
  161. package/dist/helpers/timeline-layout.js +6 -1
  162. package/dist/helpers/url-state.js +3 -2
  163. package/dist/helpers/use-menu-structure.js +1 -5
  164. package/dist/helpers/use-runtime-values.d.ts +2 -1
  165. package/dist/helpers/use-runtime-values.js +7 -3
  166. package/dist/icons/remotion-triangle.d.ts +2 -0
  167. package/dist/icons/remotion-triangle.js +7 -0
  168. package/dist/renderEntry.js +1 -1
  169. package/dist/state/composition-list.d.ts +13 -0
  170. package/dist/state/composition-list.js +21 -0
  171. package/dist/state/modals.d.ts +7 -1
  172. package/dist/state/timeline-zoom.d.ts +1 -2
  173. package/dist/state/timeline-zoom.js +9 -5
  174. package/package.json +14 -13
@@ -49,15 +49,16 @@ const use_runtime_values_1 = require("../../helpers/use-runtime-values");
49
49
  const modals_1 = require("../../state/modals");
50
50
  const timeline_sequence_hover_1 = require("../../state/timeline-sequence-hover");
51
51
  const transform_3d_mode_1 = require("../../state/transform-3d-mode");
52
- const call_api_1 = require("../call-api");
53
52
  const CompositionOrStillIcon_1 = require("../CompositionOrStillIcon");
54
53
  const ConfirmationDialog_1 = require("../ConfirmationDialog");
55
54
  const ContextMenu_1 = require("../ContextMenu");
55
+ const delete_jsx_node_api_1 = require("../delete-jsx-node-api");
56
56
  const effect_drag_and_drop_1 = require("../effect-drag-and-drop");
57
57
  const ExpandedTracksProvider_1 = require("../ExpandedTracksProvider");
58
58
  const InitialCompositionLoader_1 = require("../InitialCompositionLoader");
59
59
  const layout_1 = require("../layout");
60
60
  const NotificationCenter_1 = require("../Notifications/NotificationCenter");
61
+ const reorder_sequence_api_1 = require("../reorder-sequence-api");
61
62
  const selected_outline_types_1 = require("../selected-outline-types");
62
63
  const use_select_asset_1 = require("../use-select-asset");
63
64
  const disable_sequence_interactivity_1 = require("./disable-sequence-interactivity");
@@ -134,7 +135,9 @@ const sequenceReorderLineBase = {
134
135
  };
135
136
  const sequenceReorderAfterLineWrapper = {
136
137
  height: 0,
137
- position: 'relative',
138
+ left: 0,
139
+ position: 'absolute',
140
+ right: 0,
138
141
  };
139
142
  const sequenceReorderAfterLine = {
140
143
  ...sequenceReorderLineBase,
@@ -173,7 +176,7 @@ const getSequenceReorderDragData = (dataTransfer) => {
173
176
  const getDestinationIndex = ({ fromIndex, insertionIndex, }) => {
174
177
  return insertionIndex > fromIndex ? insertionIndex - 1 : insertionIndex;
175
178
  };
176
- const TimelineSequenceItemInner = ({ children, connectedCompositions, nestedDepth, sequence, nodePathInfo, keyframeDisplayOffset, sequenceFrameOffset, siblingIndex, }) => {
179
+ const TimelineSequenceItemInner = ({ afterDropLineOffset, connectedCompositions, nestedDepth, sequence, nodePathInfo, keyframeDisplayOffset, sequenceFrameOffset, siblingIndex, }) => {
177
180
  var _a, _b;
178
181
  var _c, _d, _e, _f;
179
182
  const nodePath = (_c = nodePathInfo === null || nodePathInfo === void 0 ? void 0 : nodePathInfo.sequenceSubscriptionKey) !== null && _c !== void 0 ? _c : null;
@@ -187,7 +190,7 @@ const TimelineSequenceItemInner = ({ children, connectedCompositions, nestedDept
187
190
  const { isHighestContext } = (0, use_keybinding_1.useKeybinding)();
188
191
  const selectAsset = (0, use_select_asset_1.useSelectAsset)();
189
192
  const selectComposition = (0, InitialCompositionLoader_1.useSelectComposition)();
190
- const { onSelect, selectable, selected, selectionItem } = (0, TimelineSelection_1.useTimelineRowSelection)(nodePathInfo);
193
+ const { onSelect, selectable, selected } = (0, TimelineSelection_1.useTimelineRowSelection)(nodePathInfo);
191
194
  const { selectItem, selectedItems } = (0, TimelineSelection_1.useTimelineSelection)();
192
195
  const containsSelection = (0, TimelineSelection_1.useTimelineRowContainsSelection)(nodePathInfo);
193
196
  const [effectDropHovered, setEffectDropHovered] = (0, react_1.useState)(false);
@@ -257,7 +260,7 @@ const TimelineSequenceItemInner = ({ children, connectedCompositions, nestedDept
257
260
  }
258
261
  }
259
262
  try {
260
- const result = await (0, call_api_1.callApi)('/api/delete-jsx-node', {
263
+ const result = await (0, delete_jsx_node_api_1.deleteJsxNode)({
261
264
  nodes: [
262
265
  {
263
266
  fileName: validatedLocation.source,
@@ -428,7 +431,7 @@ const TimelineSequenceItemInner = ({ children, connectedCompositions, nestedDept
428
431
  setSequenceDropIndicator(null);
429
432
  currentSequenceDrag = null;
430
433
  try {
431
- const result = await (0, call_api_1.callApi)('/api/reorder-sequence', {
434
+ const result = await (0, reorder_sequence_api_1.reorderSequence)({
432
435
  fileName: validatedLocation.source,
433
436
  sourceNodePath: dropTarget.dragData.nodePath,
434
437
  targetNodePath: nodePath,
@@ -905,7 +908,7 @@ const TimelineSequenceItemInner = ({ children, connectedCompositions, nestedDept
905
908
  clientId: previewServerState.clientId,
906
909
  });
907
910
  }, [canDropEffect, nodePath, previewServerState, validatedLocation]);
908
- const trackRow = (jsx_runtime_1.jsx(TimelineRowChrome_1.TimelineRowChrome, { depth: nestedDepth, eye: canToggleVisibility ? (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEye, { type: sequence.type === 'audio' ? 'speaker' : 'eye', hidden: isItemHidden, onInvoked: onToggleVisibility })) : (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEyeSpacer, {})), arrow: hasExpandableContent && nodePathInfo !== null ? (jsx_runtime_1.jsx(TimelineSequenceExpandArrow, { disabled: !previewInteractive, isExpanded: isExpanded, nodePathInfo: nodePathInfo, sequence: sequence })) : (jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowSpacer, {})), style: rowStyle, selected: selected, selectable: selectable, selectionItem: selectionItem, onSelect: onSelect, showSelectedBackground: true, containsSelection: containsSelection, hovered: hovered, isFieldRow: false, outerHeight: outerHeight, onDragLeave: canDropEffect ? onEffectDragLeave : undefined, onDragOver: canDropEffect ? onEffectDragOver : undefined, onDrop: canDropEffect ? onEffectDrop : undefined, onDoubleClick: canHandleSequenceDoubleClick ? onSequenceDoubleClick : undefined, onPointerEnter: onPointerEnter, onPointerLeave: onPointerLeave, children: jsx_runtime_1.jsxs("div", { style: labelContainerStyle, children: [connectedCompositions.length > 0 ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
911
+ const trackRow = (jsx_runtime_1.jsx(TimelineRowChrome_1.TimelineRowChrome, { depth: nestedDepth, eye: canToggleVisibility ? (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEye, { type: sequence.type === 'audio' ? 'speaker' : 'eye', hidden: isItemHidden, onInvoked: onToggleVisibility })) : (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEyeSpacer, {})), arrow: hasExpandableContent && nodePathInfo !== null ? (jsx_runtime_1.jsx(TimelineSequenceExpandArrow, { disabled: !previewInteractive, isExpanded: isExpanded, nodePathInfo: nodePathInfo, sequence: sequence })) : (jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowSpacer, {})), style: rowStyle, selected: selected, selectable: selectable, onSelect: onSelect, showSelectedBackground: true, containsSelection: containsSelection, hovered: hovered, isFieldRow: false, outerHeight: outerHeight, onDragLeave: canDropEffect ? onEffectDragLeave : undefined, onDragOver: canDropEffect ? onEffectDragOver : undefined, onDrop: canDropEffect ? onEffectDrop : undefined, onDoubleClick: canHandleSequenceDoubleClick ? onSequenceDoubleClick : undefined, onPointerEnter: onPointerEnter, onPointerLeave: onPointerLeave, children: jsx_runtime_1.jsxs("div", { style: labelContainerStyle, children: [connectedCompositions.length > 0 ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
909
912
  jsx_runtime_1.jsx(CompositionOrStillIcon_1.CompositionOrStillIcon, { color: (0, TimelineSelection_1.getTimelineColor)(false, false), composition: connectedCompositions[0], style: connectedCompositionIconStyle }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 })
910
913
  ] })) : null, jsx_runtime_1.jsx(TimelineSequenceName_1.TimelineSequenceName, { displayName: timelineDisplayName, fallbackDisplayName: fallbackDisplayName, selected: selected, containsSelection: containsSelection, editing: isRenaming, onCancelEditing: onCancelRenaming, onSaveName: onSaveName }), numberOfHiddenDuplicates > 0 ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
911
914
  jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(TimelineDuplicateCount_1.TimelineDuplicateCount, { count: numberOfHiddenDuplicates })
@@ -914,12 +917,15 @@ const TimelineSequenceItemInner = ({ children, connectedCompositions, nestedDept
914
917
  " ",
915
918
  jsx_runtime_1.jsx(TimelineMediaInfo_1.TimelineMediaInfo, { src: mediaSrc })
916
919
  ] })) : null] }) }));
917
- const draggableTrackRow = canHandleSequenceDrag ? (jsx_runtime_1.jsxs("div", { draggable: canReorderSequence, onDragStart: onSequenceDragStart, onDragEnd: onSequenceDragEnd, onDragOver: onSequenceDragOver, onDragLeave: onSequenceDragLeave, onDrop: onSequenceDrop, style: sequenceReorderWrapper, children: [sequenceReorderLineStyle ? (jsx_runtime_1.jsx("div", { style: sequenceReorderLineStyle })) : null, trackRow] })) : (trackRow);
920
+ const draggableTrackRow = canHandleSequenceDrag ? (jsx_runtime_1.jsxs("div", { draggable: canReorderSequence, onDragStart: onSequenceDragStart, onDragEnd: onSequenceDragEnd, onDragOver: onSequenceDragOver, onDragLeave: onSequenceDragLeave, onDrop: onSequenceDrop, style: sequenceReorderWrapper, children: [sequenceReorderLineStyle ? (jsx_runtime_1.jsx("div", { style: sequenceReorderLineStyle })) : null, trackRow, sequenceDropIndicator === 'after' ? (jsx_runtime_1.jsx("div", { style: {
921
+ ...sequenceReorderAfterLineWrapper,
922
+ top: afterDropLineOffset,
923
+ }, children: jsx_runtime_1.jsx("div", { style: sequenceReorderAfterLine }) })) : null] })) : (trackRow);
918
924
  return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [previewConnected || window.remotion_isReadOnlyStudio ? (jsx_runtime_1.jsx(ContextMenu_1.ContextMenu, { getItems: getContextMenuItems, children: draggableTrackRow })) : (draggableTrackRow), previewConnected &&
919
925
  (0, interactivity_enabled_1.isStudioInteractivityEnabled)() &&
920
926
  isExpanded &&
921
927
  hasExpandableContent &&
922
928
  nodePathInfo &&
923
- validatedLocation ? (jsx_runtime_1.jsx(TimelineExpandedSection_1.TimelineExpandedSection, { sequence: sequence, validatedLocation: validatedLocation, nodePathInfo: nodePathInfo, nestedDepth: nestedDepth, keyframeDisplayOffset: keyframeDisplayOffset })) : null, children, sequenceDropIndicator === 'after' ? (jsx_runtime_1.jsx("div", { style: sequenceReorderAfterLineWrapper, children: jsx_runtime_1.jsx("div", { style: sequenceReorderAfterLine }) })) : null] }));
929
+ validatedLocation ? (jsx_runtime_1.jsx(TimelineExpandedSection_1.TimelineExpandedSection, { sequence: sequence, validatedLocation: validatedLocation, nodePathInfo: nodePathInfo, nestedDepth: nestedDepth, keyframeDisplayOffset: keyframeDisplayOffset })) : null] }));
924
930
  };
925
931
  exports.TimelineSequenceItem = react_1.default.memo(TimelineSequenceItemInner);
@@ -27,6 +27,7 @@ export declare const TimelineSequencePropItem: React.FC<{
27
27
  readonly nodePathInfo: SequenceNodePathInfo;
28
28
  readonly schema: InteractivitySchema;
29
29
  readonly keyframeDisplayOffset: number;
30
- readonly keyframeControlsMode?: TimelineKeyframeControlsMode;
30
+ readonly keyframeControlsMode: TimelineKeyframeControlsMode;
31
+ readonly runtimeValue: unknown;
31
32
  }>;
32
33
  export {};
@@ -236,7 +236,7 @@ const TimelineSequenceKeyframedValueUnmemoized = (props) => {
236
236
  return props.sourceFrame !== undefined ? (jsx_runtime_1.jsx(TimelineSequenceKeyframedValueAtSourceFrame, { ...valueProps, sourceFrame: props.sourceFrame })) : (jsx_runtime_1.jsx(TimelineSequenceKeyframedValueAtCurrentFrame, { ...valueProps, keyframeDisplayOffset: props.keyframeDisplayOffset }));
237
237
  };
238
238
  exports.TimelineSequenceKeyframedValue = react_1.default.memo(TimelineSequenceKeyframedValueUnmemoized);
239
- const TimelineSequencePropItem = ({ field, validatedLocation, rowDepth, nodePath, nodePathInfo, schema, keyframeDisplayOffset, keyframeControlsMode = 'timeline', }) => {
239
+ const TimelineSequencePropItem = ({ field, validatedLocation, rowDepth, nodePath, nodePathInfo, schema, keyframeDisplayOffset, keyframeControlsMode, runtimeValue, }) => {
240
240
  var _a;
241
241
  const { propStatuses: visualModePropStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModePropStatusesContext);
242
242
  const { getDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeDragOverridesContext);
@@ -356,7 +356,7 @@ const TimelineSequencePropItem = ({ field, validatedLocation, rowDepth, nodePath
356
356
  if (propStatus === null) {
357
357
  return null;
358
358
  }
359
- const fieldValue = isKeyframedStatus(propStatus) ? (jsx_runtime_1.jsx(exports.TimelineSequenceKeyframedValue, { field: field, fileName: validatedLocation.source, nodePath: nodePath, schema: schema, propStatus: propStatus, keyframeDisplayOffset: keyframeDisplayOffset })) : propStatus.status === 'static' ? (jsx_runtime_1.jsx(Value, { field: field, nodePath: nodePath, validatedLocation: validatedLocation, schema: schema, propStatus: propStatus })) : (jsx_runtime_1.jsx(TimelineSchemaField_1.TimelineNonEditableStatus, { propStatus: propStatus }));
359
+ const fieldValue = isKeyframedStatus(propStatus) ? (jsx_runtime_1.jsx(exports.TimelineSequenceKeyframedValue, { field: field, fileName: validatedLocation.source, nodePath: nodePath, schema: schema, propStatus: propStatus, keyframeDisplayOffset: keyframeDisplayOffset })) : propStatus.status === 'static' ? (jsx_runtime_1.jsx(Value, { field: field, nodePath: nodePath, validatedLocation: validatedLocation, schema: schema, propStatus: propStatus })) : (jsx_runtime_1.jsx(TimelineSchemaField_1.TimelineNonEditableStatus, { propStatus: propStatus, field: field, runtimeValue: runtimeValue, validatedLocation: validatedLocation }));
360
360
  if (field.typeName === 'asset' && field.key === 'src') {
361
361
  return (jsx_runtime_1.jsx("div", { style: {
362
362
  ...inlineSourceFieldRow,
@@ -364,7 +364,7 @@ const TimelineSequencePropItem = ({ field, validatedLocation, rowDepth, nodePath
364
364
  ...style,
365
365
  }, children: fieldValue }));
366
366
  }
367
- const row = (jsx_runtime_1.jsx(TimelineRowChrome_1.TimelineRowChrome, { depth: rowDepth, eye: jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEyeSpacer, {}), keyframeControls: keyframeControls, arrow: jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowSpacer, {}), style: style, selected: selection.selected, selectable: selection.selectable, selectionItem: selection.selectionItem, onSelect: selection.onSelect, onDoubleClick: onPropertyDoubleClick, showSelectedBackground: true, containsSelection: false, isFieldRow: true, outerHeight: null, children: jsx_runtime_1.jsx(TimelineFieldRowContent_1.TimelineFieldRowContent, { field: field, rowDepth: rowDepth, selected: selection.selected, keyframeControls: keyframeControls, children: fieldValue }) }));
367
+ const row = (jsx_runtime_1.jsx(TimelineRowChrome_1.TimelineRowChrome, { depth: rowDepth, eye: jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEyeSpacer, {}), keyframeControls: keyframeControls, arrow: jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowSpacer, {}), style: style, selected: selection.selected, selectable: selection.selectable, onSelect: selection.onSelect, onDoubleClick: onPropertyDoubleClick, showSelectedBackground: true, containsSelection: false, isFieldRow: true, outerHeight: null, children: jsx_runtime_1.jsx(TimelineFieldRowContent_1.TimelineFieldRowContent, { field: field, rowDepth: rowDepth, selected: selection.selected, keyframeControls: keyframeControls, children: fieldValue }) }));
368
368
  return jsx_runtime_1.jsx(ContextMenu_1.ContextMenu, { getItems: getContextMenuItems, children: row });
369
369
  };
370
370
  exports.TimelineSequencePropItem = TimelineSequencePropItem;
@@ -543,21 +543,44 @@ const getTimelineSequenceFromDragTargets = ({ draggedNodePathInfo, selectedItems
543
543
  ? selectedSequenceItems.map((item) => item.nodePathInfo)
544
544
  : [draggedNodePathInfo];
545
545
  const tracks = (0, calculate_timeline_1.calculateTimeline)({ sequences, overrideIdsToNodePaths });
546
- const targets = new Map();
547
- const includedKeyframeNodePaths = new Set();
548
546
  const sequencesById = new Map(sequences.map((sequence) => [sequence.id, sequence]));
549
- for (const nodePathInfo of targetNodePathInfos) {
547
+ const selectedSequences = targetNodePathInfos.flatMap((nodePathInfo) => {
550
548
  const track = findSequenceTrack({ tracks, nodePathInfo });
551
549
  const originalSequence = track
552
- ? sequences.find((sequence) => sequence.id === track.sequence.id)
553
- : null;
554
- if (!track ||
555
- !track.nodePathInfo ||
556
- !originalSequence ||
557
- !isFromDraggableSequence(originalSequence)) {
550
+ ? sequencesById.get(track.sequence.id)
551
+ : undefined;
552
+ if (!(track === null || track === void 0 ? void 0 : track.nodePathInfo) || !originalSequence) {
553
+ return [];
554
+ }
555
+ return [
556
+ {
557
+ nodePath: track.nodePathInfo.sequenceSubscriptionKey,
558
+ originalSequence,
559
+ },
560
+ ];
561
+ });
562
+ if (selectedSequences.length !== targetNodePathInfos.length) {
563
+ return null;
564
+ }
565
+ const selectedSequenceIds = new Set(selectedSequences.map(({ originalSequence }) => originalSequence.id));
566
+ const sequencesWithoutSelectedAncestors = selectedSequences.filter(({ originalSequence }) => {
567
+ var _a;
568
+ var _b;
569
+ let parentId = originalSequence.parent;
570
+ while (parentId !== null) {
571
+ if (selectedSequenceIds.has(parentId)) {
572
+ return false;
573
+ }
574
+ parentId = (_b = (_a = sequencesById.get(parentId)) === null || _a === void 0 ? void 0 : _a.parent) !== null && _b !== void 0 ? _b : null;
575
+ }
576
+ return true;
577
+ });
578
+ const targets = new Map();
579
+ const includedKeyframeNodePaths = new Set();
580
+ for (const { nodePath, originalSequence, } of sequencesWithoutSelectedAncestors) {
581
+ if (!isFromDraggableSequence(originalSequence)) {
558
582
  return null;
559
583
  }
560
- const nodePath = track.nodePathInfo.sequenceSubscriptionKey;
561
584
  if (!canUpdateFrom({ propStatuses, nodePath })) {
562
585
  return null;
563
586
  }
@@ -11,12 +11,21 @@ const imperative_state_1 = require("./imperative-state");
11
11
  const timeline_refs_1 = require("./timeline-refs");
12
12
  const TimelineSliderHandle_1 = require("./TimelineSliderHandle");
13
13
  const TimelineWidthProvider_1 = require("./TimelineWidthProvider");
14
- const container = {
14
+ const clippingContainer = {
15
15
  position: 'absolute',
16
- bottom: 0,
17
16
  top: 0,
17
+ left: 0,
18
+ width: '100%',
19
+ height: '100vh',
20
+ overflow: 'hidden',
18
21
  pointerEvents: 'none',
19
22
  };
23
+ const slider = {
24
+ position: 'absolute',
25
+ top: 0,
26
+ left: 0,
27
+ height: '100%',
28
+ };
20
29
  const PLAYHEAD_LINE_WIDTH = 1;
21
30
  const line = {
22
31
  height: '100vh',
@@ -25,9 +34,9 @@ const line = {
25
34
  backgroundColor: colors_1.TIMELINE_PLAYHEAD_COLOR,
26
35
  };
27
36
  const PLAYHEAD_CENTER_OFFSET = PLAYHEAD_LINE_WIDTH / 2;
28
- const getTimelineSliderTransform = ({ durationInFrames, frame, width, }) => {
37
+ const getTimelineSliderTransform = ({ durationInFrames, frame, scrollLeft, width, }) => {
29
38
  const left = (0, get_left_of_timeline_slider_1.getXPositionOfItemInTimelineImperatively)(frame, durationInFrames, width);
30
- return `translateX(${left - PLAYHEAD_CENTER_OFFSET}px)`;
39
+ return `translateX(${left - scrollLeft - PLAYHEAD_CENTER_OFFSET}px)`;
31
40
  };
32
41
  exports.redrawTimelineSliderFast = (0, react_1.createRef)();
33
42
  const TimelineSlider = () => {
@@ -57,14 +66,30 @@ const TimelineSliderInner = () => {
57
66
  var _a;
58
67
  const el = ref.current;
59
68
  const measuredWidth = (_a = timeline_refs_1.sliderAreaRef.current) === null || _a === void 0 ? void 0 : _a.clientWidth;
60
- if (!el || measuredWidth === undefined || measuredWidth === 0) {
69
+ const scrollable = timeline_refs_1.scrollableRef.current;
70
+ if (!el ||
71
+ !scrollable ||
72
+ measuredWidth === undefined ||
73
+ measuredWidth === 0) {
61
74
  return;
62
75
  }
63
- el.style.transform = getTimelineSliderTransform({
64
- durationInFrames: videoConfig.durationInFrames,
65
- frame: timelinePosition,
66
- width: measuredWidth,
67
- });
76
+ const draw = (frame) => {
77
+ el.style.transform = getTimelineSliderTransform({
78
+ durationInFrames: videoConfig.durationInFrames,
79
+ frame,
80
+ scrollLeft: scrollable.scrollLeft,
81
+ width: measuredWidth,
82
+ });
83
+ };
84
+ draw(timelinePosition);
85
+ // Read the frame imperatively on scroll: during edge auto-scrolling, the
86
+ // scroll event can fire before React has committed the seek, and drawing
87
+ // with the stale `timelinePosition` closure makes the playhead flicker.
88
+ const onScroll = () => draw((0, imperative_state_1.getCurrentFrame)());
89
+ scrollable.addEventListener('scroll', onScroll);
90
+ return () => {
91
+ scrollable.removeEventListener('scroll', onScroll);
92
+ };
68
93
  }, [
69
94
  timelinePosition,
70
95
  videoConfig.durationInFrames,
@@ -74,8 +99,8 @@ const TimelineSliderInner = () => {
74
99
  (0, react_1.useImperativeHandle)(exports.redrawTimelineSliderFast, () => {
75
100
  return {
76
101
  draw: (frame, width) => {
77
- var _a;
78
- var _b;
102
+ var _a, _b;
103
+ var _c, _d;
79
104
  const { current } = ref;
80
105
  if (!current) {
81
106
  throw new Error('unexpectedly did not have ref to timelineslider');
@@ -83,29 +108,13 @@ const TimelineSliderInner = () => {
83
108
  current.style.transform = getTimelineSliderTransform({
84
109
  durationInFrames: (0, imperative_state_1.getCurrentDuration)(),
85
110
  frame,
86
- width: (_b = width !== null && width !== void 0 ? width : (_a = timeline_refs_1.sliderAreaRef.current) === null || _a === void 0 ? void 0 : _a.clientWidth) !== null && _b !== void 0 ? _b : 0,
111
+ scrollLeft: (_c = (_a = timeline_refs_1.scrollableRef.current) === null || _a === void 0 ? void 0 : _a.scrollLeft) !== null && _c !== void 0 ? _c : 0,
112
+ width: (_d = width !== null && width !== void 0 ? width : (_b = timeline_refs_1.sliderAreaRef.current) === null || _b === void 0 ? void 0 : _b.clientWidth) !== null && _d !== void 0 ? _d : 0,
87
113
  });
88
114
  },
89
115
  };
90
116
  }, []);
91
- (0, react_1.useEffect)(() => {
92
- const currentRef = ref.current;
93
- if (!currentRef) {
94
- return;
95
- }
96
- const { current } = timeline_refs_1.timelineVerticalScroll;
97
- if (!current) {
98
- return;
99
- }
100
- const onScroll = () => {
101
- currentRef.style.top = current.scrollTop + 'px';
102
- };
103
- current.addEventListener('scroll', onScroll);
104
- return () => {
105
- current.removeEventListener('scroll', onScroll);
106
- };
107
- }, []);
108
- return (jsx_runtime_1.jsxs("div", { ref: ref, style: container, children: [
109
- jsx_runtime_1.jsx("div", { style: line }), jsx_runtime_1.jsx(TimelineSliderHandle_1.TimelineSliderHandle, {})
110
- ] }));
117
+ return (jsx_runtime_1.jsx("div", { style: clippingContainer, children: jsx_runtime_1.jsxs("div", { ref: ref, style: slider, children: [
118
+ jsx_runtime_1.jsx("div", { style: line }), jsx_runtime_1.jsx(TimelineSliderHandle_1.TimelineSliderHandle, {})
119
+ ] }) }));
111
120
  };
@@ -53,16 +53,6 @@ const container = {
53
53
  top: 0,
54
54
  borderBottom: `${timeline_layout_1.TIMELINE_ITEM_BORDER_BOTTOM}px solid ${colors_1.TIMELINE_TRACK_SEPARATOR}`,
55
55
  };
56
- const tick = {
57
- width: 1,
58
- backgroundColor: colors_1.WHITE_ALPHA_15,
59
- height: 20,
60
- position: 'absolute',
61
- };
62
- const secondTick = {
63
- ...tick,
64
- height: 15,
65
- };
66
56
  const TICK_LABEL_FONT_SIZE = 12;
67
57
  const TICK_LABEL_MARGIN_LEFT = 8;
68
58
  const TICK_LABEL_MIN_GAP = 16;
@@ -70,12 +60,6 @@ const MIN_SPACING_BETWEEN_FRAME_TICKS_PX = 5;
70
60
  const MIN_SPACING_BETWEEN_TIME_TICKS_PX = 16;
71
61
  const MIN_SPACING_BETWEEN_MEDIUM_FRAME_TICKS_PX = 24;
72
62
  const MIN_SPACING_BETWEEN_MEDIUM_TIME_TICKS_PX = 48;
73
- const tickLabel = {
74
- fontSize: TICK_LABEL_FONT_SIZE,
75
- marginLeft: TICK_LABEL_MARGIN_LEFT,
76
- marginTop: 7,
77
- color: colors_1.LIGHT_TEXT,
78
- };
79
63
  const timeValue = {
80
64
  height: exports.TIMELINE_TIME_INDICATOR_HEIGHT,
81
65
  position: 'absolute',
@@ -205,103 +189,111 @@ const TimelineTimeIndicators = () => {
205
189
  };
206
190
  exports.TimelineTimeIndicators = TimelineTimeIndicators;
207
191
  const TimelineTimeIndicatorsInner = react_1.default.memo(({ windowWidth, durationInFrames, fps }) => {
208
- const ref = (0, react_1.useRef)(null);
209
- (0, react_1.useEffect)(() => {
210
- const currentRef = ref.current;
211
- if (!currentRef) {
192
+ const canvasRef = (0, react_1.useRef)(null);
193
+ (0, react_1.useLayoutEffect)(() => {
194
+ const canvas = canvasRef.current;
195
+ const scrollable = timeline_refs_1.scrollableRef.current;
196
+ if (!canvas || !scrollable) {
212
197
  return;
213
198
  }
214
- const { current } = timeline_refs_1.timelineVerticalScroll;
215
- if (!current) {
199
+ const context = canvas.getContext('2d');
200
+ if (!context) {
216
201
  return;
217
202
  }
218
- const onScroll = () => {
219
- currentRef.style.top = current.scrollTop + 'px';
220
- };
221
- current.addEventListener('scroll', onScroll);
222
- return () => {
223
- current.removeEventListener('scroll', onScroll);
224
- };
225
- }, []);
226
- const style = (0, react_1.useMemo)(() => {
227
- return {
228
- ...container,
229
- width: windowWidth,
230
- overflow: 'hidden',
231
- pointerEvents: 'none',
232
- };
233
- }, [windowWidth]);
234
- const ticks = (0, react_1.useMemo)(() => {
235
203
  const frameInterval = (0, timeline_scroll_logic_1.getFrameIncrementFromWidth)(durationInFrames, windowWidth);
236
204
  const maxTickLabelWidth = (0, render_frame_1.renderFrame)(durationInFrames - 1, fps).length *
237
205
  TICK_LABEL_FONT_SIZE *
238
206
  0.6;
239
- const minSpacingBetweenTickLabelsPx = TICK_LABEL_MARGIN_LEFT + maxTickLabelWidth + TICK_LABEL_MIN_GAP;
240
- const seconds = Math.floor(durationInFrames / fps);
241
- const rawSecondMarkerEveryNth = minSpacingBetweenTickLabelsPx / (frameInterval * fps);
242
207
  const tickScale = (0, exports.getTimelineTickScale)({
243
208
  fps,
244
209
  frameInterval,
245
- rawSecondMarkerEveryNth,
210
+ rawSecondMarkerEveryNth: (TICK_LABEL_MARGIN_LEFT + maxTickLabelWidth + TICK_LABEL_MIN_GAP) /
211
+ (frameInterval * fps),
246
212
  });
247
- // Labeled ticks use human-friendly time intervals.
248
- const secondTicks = [];
249
- for (let index = 0; index < seconds; index += tickScale.labelEverySeconds) {
250
- secondTicks.push({
251
- frame: index * fps,
252
- style: {
253
- ...secondTick,
254
- left: frameInterval * index * fps + timeline_layout_1.TIMELINE_PADDING,
255
- },
256
- showTime: index > 0,
257
- });
258
- }
259
- const hasSecondTick = new Set(secondTicks.map((t) => t.frame));
260
- const subdivisionTicks = [];
261
- const { minorTickEvery, mediumTickEvery } = tickScale;
262
- if ((minorTickEvery === null || minorTickEvery === void 0 ? void 0 : minorTickEvery.unit) === 'frames') {
263
- for (let frame = 0; frame < durationInFrames; frame += minorTickEvery.interval) {
264
- if (hasSecondTick.has(frame)) {
265
- continue;
266
- }
267
- subdivisionTicks.push({
268
- frame,
269
- style: {
270
- ...tick,
271
- left: frameInterval * frame + timeline_layout_1.TIMELINE_PADDING,
272
- height: (Number.isInteger(fps) && frame % fps === 0) ||
273
- ((mediumTickEvery === null || mediumTickEvery === void 0 ? void 0 : mediumTickEvery.unit) === 'frames' &&
274
- frame % mediumTickEvery.interval === 0)
275
- ? 5
276
- : 2,
277
- },
278
- showTime: false,
279
- });
213
+ const draw = () => {
214
+ const { clientWidth: width, scrollLeft } = scrollable;
215
+ const pixelRatio = window.devicePixelRatio;
216
+ const canvasWidth = Math.ceil(width * pixelRatio);
217
+ const canvasHeight = exports.TIMELINE_TIME_INDICATOR_HEIGHT * pixelRatio;
218
+ if (canvas.width !== canvasWidth || canvas.height !== canvasHeight) {
219
+ canvas.width = canvasWidth;
220
+ canvas.height = canvasHeight;
221
+ canvas.style.width = `${width}px`;
222
+ canvas.style.height = `${exports.TIMELINE_TIME_INDICATOR_HEIGHT}px`;
280
223
  }
281
- }
282
- if ((minorTickEvery === null || minorTickEvery === void 0 ? void 0 : minorTickEvery.unit) === 'seconds') {
283
- for (let second = 0; second < seconds; second += minorTickEvery.interval) {
224
+ context.resetTransform();
225
+ context.clearRect(0, 0, canvas.width, canvas.height);
226
+ context.scale(pixelRatio, pixelRatio);
227
+ context.fillStyle = colors_1.WHITE_ALPHA_15;
228
+ const firstFrame = Math.max(0, Math.floor((scrollLeft - timeline_layout_1.TIMELINE_PADDING) / frameInterval));
229
+ const lastFrame = Math.min(durationInFrames - 1, Math.ceil((scrollLeft + width - timeline_layout_1.TIMELINE_PADDING) / frameInterval));
230
+ const xForFrame = (frame) => Math.round(frameInterval * frame + timeline_layout_1.TIMELINE_PADDING - scrollLeft) + 0.5;
231
+ const drawTick = (frame, height) => {
232
+ const x = xForFrame(frame);
233
+ context.fillRect(x, 0, 1, height);
234
+ };
235
+ const firstLabelSecond = Math.ceil(firstFrame / fps / tickScale.labelEverySeconds) *
236
+ tickScale.labelEverySeconds;
237
+ const seconds = Math.floor(durationInFrames / fps);
238
+ for (let second = firstLabelSecond; second < seconds && second * fps <= lastFrame; second += tickScale.labelEverySeconds) {
284
239
  const frame = second * fps;
285
- if (hasSecondTick.has(frame)) {
286
- continue;
240
+ drawTick(frame, 15);
241
+ if (second > 0) {
242
+ context.fillStyle = colors_1.LIGHT_TEXT;
243
+ context.font = `${TICK_LABEL_FONT_SIZE}px ${getComputedStyle(canvas).fontFamily}`;
244
+ context.textBaseline = 'top';
245
+ context.fillText((0, render_frame_1.renderFrame)(frame, fps), xForFrame(frame) + TICK_LABEL_MARGIN_LEFT, 7);
246
+ context.fillStyle = colors_1.WHITE_ALPHA_15;
287
247
  }
288
- subdivisionTicks.push({
289
- frame,
290
- style: {
291
- ...tick,
292
- left: frameInterval * frame + timeline_layout_1.TIMELINE_PADDING,
293
- height: (mediumTickEvery === null || mediumTickEvery === void 0 ? void 0 : mediumTickEvery.unit) === 'seconds' &&
294
- second % mediumTickEvery.interval === 0
295
- ? 5
296
- : 2,
297
- },
298
- showTime: false,
299
- });
300
248
  }
301
- }
302
- return [...secondTicks, ...subdivisionTicks];
249
+ const { minorTickEvery, mediumTickEvery } = tickScale;
250
+ if ((minorTickEvery === null || minorTickEvery === void 0 ? void 0 : minorTickEvery.unit) === 'frames') {
251
+ const firstTick = Math.ceil(firstFrame / minorTickEvery.interval) *
252
+ minorTickEvery.interval;
253
+ for (let frame = firstTick; frame <= lastFrame; frame += minorTickEvery.interval) {
254
+ if (frame % (tickScale.labelEverySeconds * fps) === 0) {
255
+ continue;
256
+ }
257
+ drawTick(frame, (Number.isInteger(fps) && frame % fps === 0) ||
258
+ ((mediumTickEvery === null || mediumTickEvery === void 0 ? void 0 : mediumTickEvery.unit) === 'frames' &&
259
+ frame % mediumTickEvery.interval === 0)
260
+ ? 5
261
+ : 2);
262
+ }
263
+ }
264
+ if ((minorTickEvery === null || minorTickEvery === void 0 ? void 0 : minorTickEvery.unit) === 'seconds') {
265
+ const firstSecond = Math.ceil(firstFrame / fps / minorTickEvery.interval) *
266
+ minorTickEvery.interval;
267
+ for (let second = firstSecond; second < seconds && second * fps <= lastFrame; second += minorTickEvery.interval) {
268
+ if (second % tickScale.labelEverySeconds === 0) {
269
+ continue;
270
+ }
271
+ drawTick(second * fps, (mediumTickEvery === null || mediumTickEvery === void 0 ? void 0 : mediumTickEvery.unit) === 'seconds' &&
272
+ second % mediumTickEvery.interval === 0
273
+ ? 5
274
+ : 2);
275
+ }
276
+ }
277
+ };
278
+ const onScroll = () => {
279
+ draw();
280
+ };
281
+ const resizeObserver = new ResizeObserver(draw);
282
+ draw();
283
+ scrollable.addEventListener('scroll', onScroll);
284
+ resizeObserver.observe(scrollable);
285
+ return () => {
286
+ scrollable.removeEventListener('scroll', onScroll);
287
+ resizeObserver.disconnect();
288
+ };
303
289
  }, [durationInFrames, fps, windowWidth]);
304
- return (jsx_runtime_1.jsx("div", { ref: ref, style: style, children: ticks.map((t) => {
305
- return (jsx_runtime_1.jsx("div", { style: t.style, children: t.showTime ? (jsx_runtime_1.jsx("div", { style: tickLabel, children: (0, render_frame_1.renderFrame)(t.frame, fps) })) : null }, t.frame));
306
- }) }));
290
+ const style = (0, react_1.useMemo)(() => {
291
+ return {
292
+ ...container,
293
+ width: windowWidth,
294
+ overflow: 'hidden',
295
+ pointerEvents: 'none',
296
+ };
297
+ }, [windowWidth]);
298
+ return (jsx_runtime_1.jsx("div", { style: style, children: jsx_runtime_1.jsx("canvas", { ref: canvasRef, style: { position: 'absolute', top: 0, left: 0 } }) }));
307
299
  });
@@ -1,6 +1,4 @@
1
1
  import React from 'react';
2
- import type { TimelineTrackData } from '../../helpers/get-timeline-sequence-sort-key';
3
2
  export declare const TimelineTracks: React.NamedExoticComponent<{
4
- readonly timeline: TimelineTrackData[];
5
3
  readonly hasBeenCut: boolean;
6
4
  }>;
@@ -38,16 +38,18 @@ const jsx_runtime_1 = require("react/jsx-runtime");
38
38
  const react_1 = __importStar(require("react"));
39
39
  const timeline_layout_1 = require("../../helpers/timeline-layout");
40
40
  const MaxTimelineTracks_1 = require("./MaxTimelineTracks");
41
- const TimelineTimeIndicators_1 = require("./TimelineTimeIndicators");
42
41
  const TimelineTrack_1 = require("./TimelineTrack");
42
+ const TimelineVirtualization_1 = require("./TimelineVirtualization");
43
43
  const content = {
44
44
  paddingLeft: timeline_layout_1.TIMELINE_PADDING,
45
45
  paddingRight: timeline_layout_1.TIMELINE_PADDING,
46
+ position: 'relative',
46
47
  };
47
48
  const timelineContent = {
48
49
  minHeight: '100%',
49
50
  };
50
- const TimelineTracksInner = ({ timeline, hasBeenCut }) => {
51
+ const TimelineTracksInner = ({ hasBeenCut }) => {
52
+ const { rows, tracksEnd, virtualItems } = (0, TimelineVirtualization_1.useTimelineVirtualization)();
51
53
  const timelineStyle = (0, react_1.useMemo)(() => {
52
54
  return {
53
55
  ...timelineContent,
@@ -55,7 +57,12 @@ const TimelineTracksInner = ({ timeline, hasBeenCut }) => {
55
57
  };
56
58
  }, []);
57
59
  return (jsx_runtime_1.jsxs("div", { style: timelineStyle, children: [
58
- jsx_runtime_1.jsxs("div", { style: content, children: [
59
- jsx_runtime_1.jsx(TimelineTimeIndicators_1.TimelineTimePadding, {}), timeline.map((track) => (jsx_runtime_1.jsx(TimelineTrack_1.TimelineTrack, { track: track }, track.sequence.id)))] }), hasBeenCut ? jsx_runtime_1.jsx(MaxTimelineTracks_1.MaxTimelineTracksReached, {}) : null] }));
60
+ jsx_runtime_1.jsx("div", { style: { ...content, height: tracksEnd }, children: virtualItems.map((virtualItem) => (jsx_runtime_1.jsx("div", { style: {
61
+ height: virtualItem.size,
62
+ left: timeline_layout_1.TIMELINE_PADDING,
63
+ position: 'absolute',
64
+ right: timeline_layout_1.TIMELINE_PADDING,
65
+ top: virtualItem.start,
66
+ }, children: jsx_runtime_1.jsx(TimelineTrack_1.TimelineTrack, { track: rows[virtualItem.index].track }) }, virtualItem.key))) }), hasBeenCut ? jsx_runtime_1.jsx(MaxTimelineTracks_1.MaxTimelineTracksReached, {}) : null] }));
60
67
  };
61
68
  exports.TimelineTracks = react_1.default.memo(TimelineTracksInner);
@@ -198,7 +198,7 @@ const TimelineTransformOriginField = ({ field, propStatus, effectiveValue, onSav
198
198
  serializeZ,
199
199
  ]);
200
200
  if (percent === null) {
201
- return jsx_runtime_1.jsx(TimelineSchemaField_1.UnsupportedStatus, { label: "unsupported origin" });
201
+ return (jsx_runtime_1.jsx(TimelineSchemaField_1.UnsupportedStatus, { label: "unsupported origin", formattedValue: false }));
202
202
  }
203
203
  return (jsx_runtime_1.jsxs("span", { style: containerStyle, children: [
204
204
  jsx_runtime_1.jsx(InputDragger_1.InputDragger, { type: "number", value: dragX !== null && dragX !== void 0 ? dragX : percent[0], buttonStyle: leftDraggerStyle, style: leftDraggerStyle, status: "ok", small: true, onValueChange: onXChange, onValueChangeEnd: onXChangeEnd, onTextChange: onXTextChange, min: -Infinity, max: Infinity, step: step, formatter: formatter, rightAlign: false, snapToStep: false, dragDecimalPlaces: decimalPlaces, "aria-label": "Transform origin X" }), jsx_runtime_1.jsx("div", { style: { marginLeft: -6, marginRight: -6 } }), jsx_runtime_1.jsx(InputDragger_1.InputDragger, { type: "number", value: dragY !== null && dragY !== void 0 ? dragY : percent[1], buttonStyle: rightDraggerStyle, style: rightDraggerStyle, status: "ok", small: true, onValueChange: onYChange, onValueChangeEnd: onYChangeEnd, onTextChange: onYTextChange, min: -Infinity, max: Infinity, step: step, formatter: formatter, rightAlign: false, snapToStep: false, dragDecimalPlaces: decimalPlaces, "aria-label": "Transform origin Y" }), show3D ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
@@ -3,16 +3,16 @@ import type { LoopDisplay } from 'remotion';
3
3
  export declare const TimelineVideoInfo: React.NamedExoticComponent<{
4
4
  readonly src: string;
5
5
  readonly visualizationWidth: number;
6
- readonly naturalWidth: number;
6
+ readonly displayOffsetInFrames: number;
7
+ readonly displayDurationInFrames: number;
7
8
  readonly startMediaFrom: number;
8
9
  readonly mediaFrameAtSequenceZero: number | null;
9
10
  readonly sequenceFrameOffset: number;
10
- readonly durationInFrames: number;
11
11
  readonly playbackRate: number;
12
12
  readonly volume: string | number;
13
13
  readonly doesVolumeChange: boolean;
14
- readonly premountWidth: number;
15
- readonly postmountWidth: number;
14
+ readonly muted: boolean;
15
+ readonly marginLeft: number;
16
16
  readonly loopDisplay: LoopDisplay | undefined;
17
17
  readonly frozenMediaFrame: number | null;
18
18
  readonly extendLastFrame: boolean;