@remotion/studio 4.0.513 → 4.0.515

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 (204) hide show
  1. package/dist/Studio.js +2 -1
  2. package/dist/api/install-package.js +14 -1
  3. package/dist/components/AskAiModal.js +1 -1
  4. package/dist/components/AssetSelector.js +2 -0
  5. package/dist/components/AssetSelectorItem.d.ts +2 -1
  6. package/dist/components/AssetSelectorItem.js +19 -16
  7. package/dist/components/AudioWaveform.d.ts +3 -0
  8. package/dist/components/AudioWaveform.js +65 -199
  9. package/dist/components/Canvas.js +40 -5
  10. package/dist/components/CanvasOrLoading.js +5 -0
  11. package/dist/components/CompositionSelector.js +2 -0
  12. package/dist/components/ConfigureDefaultEditorModal.js +17 -11
  13. package/dist/components/Editor.js +16 -1
  14. package/dist/components/ElementInstallConfirmation.d.ts +1 -0
  15. package/dist/components/ElementInstallConfirmation.js +4 -2
  16. package/dist/components/FixComputedValueModal.d.ts +9 -0
  17. package/dist/components/FixComputedValueModal.js +217 -0
  18. package/dist/components/InitialCompositionLoader.js +19 -0
  19. package/dist/components/InlineDropdown.js +4 -4
  20. package/dist/components/InspectorInfoHeader.js +3 -3
  21. package/dist/components/InspectorOpenInEditor.js +3 -1
  22. package/dist/components/InspectorPanel/CompositionInspector.js +37 -5
  23. package/dist/components/InspectorPanel/CompositionInspectorHeader.js +2 -2
  24. package/dist/components/InspectorPanel/ConnectedCompositionsSection.js +1 -1
  25. package/dist/components/InspectorPanel/EasingInspector.js +1 -1
  26. package/dist/components/InspectorPanel/KeyframeInspector.js +2 -2
  27. package/dist/components/InspectorPanel/SequenceInspectorHeader.js +1 -1
  28. package/dist/components/InspectorPanel/SequenceSelectionInspector.js +35 -6
  29. package/dist/components/InspectorPanel/common.d.ts +5 -5
  30. package/dist/components/InspectorPanel/common.js +8 -8
  31. package/dist/components/InspectorPanel/styles.d.ts +1 -1
  32. package/dist/components/InspectorPanel/styles.js +4 -2
  33. package/dist/components/InspectorSourceLocation.d.ts +1 -1
  34. package/dist/components/InspectorSourceLocation.js +2 -2
  35. package/dist/components/InstallPackage.d.ts +1 -1
  36. package/dist/components/InstallPackage.js +38 -6
  37. package/dist/components/LicenseKeyValidation.js +2 -2
  38. package/dist/components/Menu/MenuDivider.js +1 -1
  39. package/dist/components/Modals.js +11 -3
  40. package/dist/components/NewComposition/CodemodFooter.d.ts +1 -0
  41. package/dist/components/NewComposition/CodemodFooter.js +10 -8
  42. package/dist/components/NewComposition/DeleteComposition.js +1 -1
  43. package/dist/components/NewComposition/DeleteFolder.js +1 -1
  44. package/dist/components/NewComposition/DuplicateComposition.js +7 -2
  45. package/dist/components/NewComposition/NewComposition.js +1 -1
  46. package/dist/components/NewComposition/NewFolder.js +1 -1
  47. package/dist/components/NewComposition/RenameComposition.js +1 -1
  48. package/dist/components/NewComposition/RenameFolder.js +1 -1
  49. package/dist/components/NewComposition/duplicate-composition-api.d.ts +16 -0
  50. package/dist/components/NewComposition/duplicate-composition-api.js +16 -0
  51. package/dist/components/NoRegisterRoot.js +1 -1
  52. package/dist/components/QuickSwitcher/ExplorerQuickSwitcherTrigger.js +4 -3
  53. package/dist/components/QuickSwitcher/QuickSwitcherContent.js +1 -0
  54. package/dist/components/QuickSwitcher/fuzzy-search.js +1 -1
  55. package/dist/components/RefreshCompositionOverlay.js +1 -1
  56. package/dist/components/RenderButton.js +6 -3
  57. package/dist/components/RenderModal/GuiRenderStatus.js +3 -1
  58. package/dist/components/RenderModal/RenderModalOutputName.js +3 -3
  59. package/dist/components/RenderModal/WebRenderModal.js +10 -4
  60. package/dist/components/RenderModal/WebRenderModalAdvanced.d.ts +2 -0
  61. package/dist/components/RenderModal/WebRenderModalAdvanced.js +9 -2
  62. package/dist/components/RenderModal/render-modals.js +5 -1
  63. package/dist/components/RenderQueue/ClientRenderQueueProcessor.js +5 -1
  64. package/dist/components/RenderQueue/RenderQueueItem.js +3 -1
  65. package/dist/components/RenderQueue/RenderQueueOpenInFolder.js +3 -1
  66. package/dist/components/RenderQueue/RenderQueueRemoveItem.js +1 -1
  67. package/dist/components/RenderQueue/actions.js +12 -2
  68. package/dist/components/RenderQueue/client-side-render-types.d.ts +1 -0
  69. package/dist/components/RenderingSettings.d.ts +2 -0
  70. package/dist/components/RenderingSettings.js +355 -0
  71. package/dist/components/SelectedOutlineCanvasRotation.d.ts +1 -0
  72. package/dist/components/SelectedOutlineCanvasRotation.js +11 -4
  73. package/dist/components/SelectedOutlineElement.js +3 -3
  74. package/dist/components/SelectedOutlinePolygon.d.ts +2 -0
  75. package/dist/components/SelectedOutlinePolygon.js +54 -9
  76. package/dist/components/SettingsContext.d.ts +4 -1
  77. package/dist/components/SettingsContext.js +9 -2
  78. package/dist/components/SettingsModal.d.ts +1 -1
  79. package/dist/components/SettingsModal.js +10 -1
  80. package/dist/components/SettingsModalFooter.js +1 -1
  81. package/dist/components/StudioSettings.d.ts +2 -0
  82. package/dist/components/StudioSettings.js +185 -0
  83. package/dist/components/Timeline/LoopedIndicator.js +1 -1
  84. package/dist/components/Timeline/LoopedTimelineIndicators.d.ts +3 -0
  85. package/dist/components/Timeline/LoopedTimelineIndicators.js +22 -14
  86. package/dist/components/Timeline/Timeline.js +11 -9
  87. package/dist/components/Timeline/TimelineAssetField.d.ts +2 -2
  88. package/dist/components/Timeline/TimelineAssetField.js +1 -1
  89. package/dist/components/Timeline/TimelineClipboardKeybindings.js +6 -2
  90. package/dist/components/Timeline/TimelineDragHandler.js +62 -76
  91. package/dist/components/Timeline/TimelineEffectItem.js +23 -6
  92. package/dist/components/Timeline/TimelineEffectPropItem.d.ts +4 -2
  93. package/dist/components/Timeline/TimelineEffectPropItem.js +22 -13
  94. package/dist/components/Timeline/TimelineExpandArrowButton.js +10 -7
  95. package/dist/components/Timeline/TimelineExpandedKeyframeRow.js +4 -1
  96. package/dist/components/Timeline/TimelineExpandedRow.d.ts +1 -1
  97. package/dist/components/Timeline/TimelineExpandedRow.js +4 -4
  98. package/dist/components/Timeline/TimelineExpandedSection.js +8 -5
  99. package/dist/components/Timeline/TimelineHeightContainer.d.ts +0 -4
  100. package/dist/components/Timeline/TimelineHeightContainer.js +4 -4
  101. package/dist/components/Timeline/TimelineImageInfo.d.ts +1 -0
  102. package/dist/components/Timeline/TimelineImageInfo.js +3 -2
  103. package/dist/components/Timeline/TimelineKeyframeControls.js +6 -1
  104. package/dist/components/Timeline/TimelineList.d.ts +1 -5
  105. package/dist/components/Timeline/TimelineList.js +14 -9
  106. package/dist/components/Timeline/TimelinePinchZoom.js +5 -5
  107. package/dist/components/Timeline/TimelineRowChrome.d.ts +1 -2
  108. package/dist/components/Timeline/TimelineRowChrome.js +50 -7
  109. package/dist/components/Timeline/TimelineSchemaField.d.ts +7 -3
  110. package/dist/components/Timeline/TimelineSchemaField.js +71 -13
  111. package/dist/components/Timeline/TimelineScrollable.js +3 -1
  112. package/dist/components/Timeline/TimelineSelection.d.ts +13 -5
  113. package/dist/components/Timeline/TimelineSelection.js +95 -106
  114. package/dist/components/Timeline/TimelineSequence.js +59 -25
  115. package/dist/components/Timeline/TimelineSequenceItem.d.ts +1 -1
  116. package/dist/components/Timeline/TimelineSequenceItem.js +21 -12
  117. package/dist/components/Timeline/TimelineSequenceName.js +1 -1
  118. package/dist/components/Timeline/TimelineSequencePropItem.d.ts +2 -1
  119. package/dist/components/Timeline/TimelineSequencePropItem.js +3 -3
  120. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +33 -10
  121. package/dist/components/Timeline/TimelineSlider.js +42 -33
  122. package/dist/components/Timeline/TimelineTimeIndicators.js +90 -98
  123. package/dist/components/Timeline/TimelineTrack.js +4 -1
  124. package/dist/components/Timeline/TimelineTracks.d.ts +0 -2
  125. package/dist/components/Timeline/TimelineTracks.js +11 -4
  126. package/dist/components/Timeline/TimelineTransformOriginField.js +1 -1
  127. package/dist/components/Timeline/TimelineVideoInfo.d.ts +4 -4
  128. package/dist/components/Timeline/TimelineVideoInfo.js +155 -63
  129. package/dist/components/Timeline/TimelineViewport.d.ts +12 -0
  130. package/dist/components/Timeline/TimelineViewport.js +62 -0
  131. package/dist/components/Timeline/TimelineVirtualization.d.ts +22 -0
  132. package/dist/components/Timeline/TimelineVirtualization.js +144 -0
  133. package/dist/components/Timeline/TimelineZoomControls.js +16 -8
  134. package/dist/components/Timeline/call-add-keyframe.js +31 -3
  135. package/dist/components/Timeline/call-delete-keyframe.js +13 -3
  136. package/dist/components/Timeline/call-move-keyframe.js +11 -1
  137. package/dist/components/Timeline/call-update-keyframe-settings.js +31 -3
  138. package/dist/components/Timeline/delete-selected-timeline-item.js +8 -3
  139. package/dist/components/Timeline/duplicate-selected-timeline-item.js +4 -2
  140. package/dist/components/Timeline/get-timeline-keyframes.d.ts +1 -2
  141. package/dist/components/Timeline/get-timeline-keyframes.js +1 -8
  142. package/dist/components/Timeline/get-timeline-sequence-visible-layout.d.ts +30 -0
  143. package/dist/components/Timeline/get-timeline-sequence-visible-layout.js +61 -0
  144. package/dist/components/Timeline/save-effect-prop.js +3 -3
  145. package/dist/components/Timeline/split-selected-timeline-item.js +2 -2
  146. package/dist/components/Timeline/timeline-scroll-logic.d.ts +24 -0
  147. package/dist/components/Timeline/timeline-scroll-logic.js +127 -4
  148. package/dist/components/Timeline/use-timeline-height.d.ts +3 -5
  149. package/dist/components/Timeline/use-timeline-height.js +16 -18
  150. package/dist/components/UpdateCheck.d.ts +2 -10
  151. package/dist/components/UpdateCheck.js +8 -2
  152. package/dist/components/VisualControls/VisualControlHandle.js +8 -0
  153. package/dist/components/delete-jsx-node-api.d.ts +2 -0
  154. package/dist/components/delete-jsx-node-api.js +12 -0
  155. package/dist/components/effect-drag-and-drop.js +6 -3
  156. package/dist/components/effect-operations-api.d.ts +8 -0
  157. package/dist/components/effect-operations-api.js +52 -0
  158. package/dist/components/element-install-api.d.ts +3 -0
  159. package/dist/components/element-install-api.js +19 -0
  160. package/dist/components/import-assets.js +20 -9
  161. package/dist/components/reorder-sequence-api.d.ts +2 -0
  162. package/dist/components/reorder-sequence-api.js +12 -0
  163. package/dist/components/split-jsx-sequence-api.d.ts +2 -0
  164. package/dist/components/split-jsx-sequence-api.js +12 -0
  165. package/dist/components/split-video-from-audio-api.d.ts +2 -0
  166. package/dist/components/split-video-from-audio-api.js +12 -0
  167. package/dist/error-overlay/remotion-overlay/Overlay.js +1 -1
  168. package/dist/error-overlay/remotion-overlay/log-studio-error.js +4 -0
  169. package/dist/esm/{chunk-r46yxrjr.js → chunk-s6k99gh2.js} +1 -1
  170. package/dist/esm/{chunk-tv7r0jy3.js → chunk-v5a8vpv4.js} +11479 -7851
  171. package/dist/esm/index.mjs +7 -5
  172. package/dist/esm/internals.mjs +11479 -7851
  173. package/dist/esm/previewEntry.mjs +11311 -7683
  174. package/dist/esm/renderEntry.mjs +3 -4
  175. package/dist/helpers/browser-studio-operations.d.ts +5 -0
  176. package/dist/helpers/browser-studio-operations.js +27 -1
  177. package/dist/helpers/colors.d.ts +1 -1
  178. package/dist/helpers/colors.js +1 -1
  179. package/dist/helpers/get-timeline-max-zoom.d.ts +26 -0
  180. package/dist/helpers/get-timeline-max-zoom.js +45 -0
  181. package/dist/helpers/inject-css.js +7 -5
  182. package/dist/helpers/render-codec-label.d.ts +1 -1
  183. package/dist/helpers/retry-payload.js +1 -0
  184. package/dist/helpers/studio-runtime-config.d.ts +1 -1
  185. package/dist/helpers/studio-runtime-config.js +2 -3
  186. package/dist/helpers/timeline-layout.d.ts +3 -1
  187. package/dist/helpers/timeline-layout.js +6 -1
  188. package/dist/helpers/url-state.js +3 -2
  189. package/dist/helpers/use-max-media-duration.js +5 -3
  190. package/dist/helpers/use-media-metadata.js +37 -20
  191. package/dist/helpers/use-menu-structure.js +67 -84
  192. package/dist/helpers/use-runtime-values.d.ts +2 -1
  193. package/dist/helpers/use-runtime-values.js +7 -3
  194. package/dist/icons/cloud-download.d.ts +4 -0
  195. package/dist/icons/cloud-download.js +8 -0
  196. package/dist/icons/remotion-triangle.d.ts +2 -0
  197. package/dist/icons/remotion-triangle.js +7 -0
  198. package/dist/renderEntry.js +1 -1
  199. package/dist/state/composition-list.d.ts +13 -0
  200. package/dist/state/composition-list.js +21 -0
  201. package/dist/state/modals.d.ts +8 -2
  202. package/dist/state/timeline-zoom.d.ts +1 -2
  203. package/dist/state/timeline-zoom.js +9 -5
  204. package/package.json +14 -13
@@ -38,6 +38,7 @@ const jsx_runtime_1 = require("react/jsx-runtime");
38
38
  const react_1 = __importStar(require("react"));
39
39
  const remotion_1 = require("remotion");
40
40
  const are_sequence_node_path_infos_equal_1 = require("../../helpers/are-sequence-node-path-infos-equal");
41
+ const browser_studio_operations_1 = require("../../helpers/browser-studio-operations");
41
42
  const client_id_1 = require("../../helpers/client-id");
42
43
  const colors_1 = require("../../helpers/colors");
43
44
  const get_sequence_double_click_action_1 = require("../../helpers/get-sequence-double-click-action");
@@ -49,15 +50,16 @@ const use_runtime_values_1 = require("../../helpers/use-runtime-values");
49
50
  const modals_1 = require("../../state/modals");
50
51
  const timeline_sequence_hover_1 = require("../../state/timeline-sequence-hover");
51
52
  const transform_3d_mode_1 = require("../../state/transform-3d-mode");
52
- const call_api_1 = require("../call-api");
53
53
  const CompositionOrStillIcon_1 = require("../CompositionOrStillIcon");
54
54
  const ConfirmationDialog_1 = require("../ConfirmationDialog");
55
55
  const ContextMenu_1 = require("../ContextMenu");
56
+ const delete_jsx_node_api_1 = require("../delete-jsx-node-api");
56
57
  const effect_drag_and_drop_1 = require("../effect-drag-and-drop");
57
58
  const ExpandedTracksProvider_1 = require("../ExpandedTracksProvider");
58
59
  const InitialCompositionLoader_1 = require("../InitialCompositionLoader");
59
60
  const layout_1 = require("../layout");
60
61
  const NotificationCenter_1 = require("../Notifications/NotificationCenter");
62
+ const reorder_sequence_api_1 = require("../reorder-sequence-api");
61
63
  const selected_outline_types_1 = require("../selected-outline-types");
62
64
  const use_select_asset_1 = require("../use-select-asset");
63
65
  const disable_sequence_interactivity_1 = require("./disable-sequence-interactivity");
@@ -82,6 +84,7 @@ const labelContainerStyle = {
82
84
  alignItems: 'center',
83
85
  alignSelf: 'stretch',
84
86
  display: 'flex',
87
+ flex: 1,
85
88
  flexDirection: 'row',
86
89
  minWidth: 0,
87
90
  };
@@ -134,7 +137,9 @@ const sequenceReorderLineBase = {
134
137
  };
135
138
  const sequenceReorderAfterLineWrapper = {
136
139
  height: 0,
137
- position: 'relative',
140
+ left: 0,
141
+ position: 'absolute',
142
+ right: 0,
138
143
  };
139
144
  const sequenceReorderAfterLine = {
140
145
  ...sequenceReorderLineBase,
@@ -173,7 +178,7 @@ const getSequenceReorderDragData = (dataTransfer) => {
173
178
  const getDestinationIndex = ({ fromIndex, insertionIndex, }) => {
174
179
  return insertionIndex > fromIndex ? insertionIndex - 1 : insertionIndex;
175
180
  };
176
- const TimelineSequenceItemInner = ({ children, connectedCompositions, nestedDepth, sequence, nodePathInfo, keyframeDisplayOffset, sequenceFrameOffset, siblingIndex, }) => {
181
+ const TimelineSequenceItemInner = ({ afterDropLineOffset, connectedCompositions, nestedDepth, sequence, nodePathInfo, keyframeDisplayOffset, sequenceFrameOffset, siblingIndex, }) => {
177
182
  var _a, _b;
178
183
  var _c, _d, _e, _f;
179
184
  const nodePath = (_c = nodePathInfo === null || nodePathInfo === void 0 ? void 0 : nodePathInfo.sequenceSubscriptionKey) !== null && _c !== void 0 ? _c : null;
@@ -181,13 +186,14 @@ const TimelineSequenceItemInner = ({ children, connectedCompositions, nestedDept
181
186
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
182
187
  const previewConnected = previewServerState.type === 'connected';
183
188
  const previewInteractive = previewConnected && (0, interactivity_enabled_1.isStudioInteractivityEnabled)();
189
+ const canMutateEffects = previewConnected && (0, interactivity_enabled_1.isStudioSelectionEnabled)() && (0, browser_studio_operations_1.canUseEffectOperations)();
184
190
  const { getIsExpanded } = (0, react_1.useContext)(ExpandedTracksProvider_1.ExpandedTracksGetterContext);
185
191
  const { setPropStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
186
192
  const { setSelectedModal } = (0, react_1.useContext)(modals_1.SetSelectedModalContext);
187
193
  const { isHighestContext } = (0, use_keybinding_1.useKeybinding)();
188
194
  const selectAsset = (0, use_select_asset_1.useSelectAsset)();
189
195
  const selectComposition = (0, InitialCompositionLoader_1.useSelectComposition)();
190
- const { onSelect, selectable, selected, selectionItem } = (0, TimelineSelection_1.useTimelineRowSelection)(nodePathInfo);
196
+ const { onSelect, selectable, selected } = (0, TimelineSelection_1.useTimelineRowSelection)(nodePathInfo);
191
197
  const { selectItem, selectedItems } = (0, TimelineSelection_1.useTimelineSelection)();
192
198
  const containsSelection = (0, TimelineSelection_1.useTimelineRowContainsSelection)(nodePathInfo);
193
199
  const [effectDropHovered, setEffectDropHovered] = (0, react_1.useState)(false);
@@ -257,7 +263,7 @@ const TimelineSequenceItemInner = ({ children, connectedCompositions, nestedDept
257
263
  }
258
264
  }
259
265
  try {
260
- const result = await (0, call_api_1.callApi)('/api/delete-jsx-node', {
266
+ const result = await (0, delete_jsx_node_api_1.deleteJsxNode)({
261
267
  nodes: [
262
268
  {
263
269
  fileName: validatedLocation.source,
@@ -428,7 +434,7 @@ const TimelineSequenceItemInner = ({ children, connectedCompositions, nestedDept
428
434
  setSequenceDropIndicator(null);
429
435
  currentSequenceDrag = null;
430
436
  try {
431
- const result = await (0, call_api_1.callApi)('/api/reorder-sequence', {
437
+ const result = await (0, reorder_sequence_api_1.reorderSequence)({
432
438
  fileName: validatedLocation.source,
433
439
  sourceNodePath: dropTarget.dragData.nodePath,
434
440
  targetNodePath: nodePath,
@@ -617,7 +623,7 @@ const TimelineSequenceItemInner = ({ children, connectedCompositions, nestedDept
617
623
  setIsRenaming(true);
618
624
  }, [canRenameThisSequence]);
619
625
  const canAddEffect = (nodePathInfo === null || nodePathInfo === void 0 ? void 0 : nodePathInfo.supportsEffects) === true &&
620
- previewInteractive &&
626
+ canMutateEffects &&
621
627
  Boolean(validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source);
622
628
  const canCrop = (0, use_runtime_values_1.useRuntimeValueSelector)({
623
629
  controls: sequence.controls,
@@ -847,7 +853,7 @@ const TimelineSequenceItemInner = ({ children, connectedCompositions, nestedDept
847
853
  setPropStatuses,
848
854
  validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source,
849
855
  ]);
850
- const canDropEffect = previewInteractive &&
856
+ const canDropEffect = canMutateEffects &&
851
857
  nodePath !== null &&
852
858
  validatedLocation !== null &&
853
859
  ((_b = sequence.controls) === null || _b === void 0 ? void 0 : _b.supportsEffects) === true;
@@ -905,21 +911,24 @@ const TimelineSequenceItemInner = ({ children, connectedCompositions, nestedDept
905
911
  clientId: previewServerState.clientId,
906
912
  });
907
913
  }, [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: [
914
+ 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: 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
915
  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
- ] })) : 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: [
916
+ ] })) : null, jsx_runtime_1.jsx(TimelineSequenceName_1.TimelineSequenceName, { displayName: timelineDisplayName, fallbackDisplayName: fallbackDisplayName, selected: selected, containsSelection: containsSelection, editing: isRenaming, onCancelEditing: onCancelRenaming, onSaveName: onSaveName }), hasExpandableContent && nodePathInfo !== null ? (jsx_runtime_1.jsx(TimelineSequenceExpandArrow, { disabled: !previewInteractive, isExpanded: isExpanded, nodePathInfo: nodePathInfo, sequence: sequence })) : null, numberOfHiddenDuplicates > 0 ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
911
917
  jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(TimelineDuplicateCount_1.TimelineDuplicateCount, { count: numberOfHiddenDuplicates })
912
918
  ] })) : null, mediaSrc ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
913
919
  jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }),
914
920
  " ",
915
921
  jsx_runtime_1.jsx(TimelineMediaInfo_1.TimelineMediaInfo, { src: mediaSrc })
916
922
  ] })) : 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);
923
+ 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: {
924
+ ...sequenceReorderAfterLineWrapper,
925
+ top: afterDropLineOffset,
926
+ }, children: jsx_runtime_1.jsx("div", { style: sequenceReorderAfterLine }) })) : null] })) : (trackRow);
918
927
  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
928
  (0, interactivity_enabled_1.isStudioInteractivityEnabled)() &&
920
929
  isExpanded &&
921
930
  hasExpandableContent &&
922
931
  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] }));
932
+ validatedLocation ? (jsx_runtime_1.jsx(TimelineExpandedSection_1.TimelineExpandedSection, { sequence: sequence, validatedLocation: validatedLocation, nodePathInfo: nodePathInfo, nestedDepth: nestedDepth, keyframeDisplayOffset: keyframeDisplayOffset })) : null] }));
924
933
  };
925
934
  exports.TimelineSequenceItem = react_1.default.memo(TimelineSequenceItemInner);
@@ -24,7 +24,7 @@ const TimelineSequenceName = ({ displayName, fallbackDisplayName, selected, cont
24
24
  alignSelf: 'stretch',
25
25
  ...(0, TimelineSelection_1.getTimelineSelectedLabelStyle)(selected, false),
26
26
  display: 'inline-flex',
27
- flexShrink: 0,
27
+ flexShrink: 1,
28
28
  fontFamily: 'inherit',
29
29
  fontSize: 12,
30
30
  lineHeight: 'normal',
@@ -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
  });
@@ -52,7 +52,10 @@ const TimelineTrackUnmemoized = ({ track }) => {
52
52
  const previewServerConnected = previewServerState.type === 'connected';
53
53
  const timelineWidth = (0, react_1.useContext)(TimelineWidthProvider_1.TimelineWidthContext);
54
54
  const { hovered, onPointerEnter, onPointerLeave } = (0, timeline_sequence_hover_1.useTimelineSequenceHover)(track.nodePathInfo);
55
- const rowHighlightBackground = (0, TimelineSelection_1.useTimelineRowHighlightBackground)(track.nodePathInfo, hovered);
55
+ const rowHighlightBackground = (0, TimelineSelection_1.useTimelineRowHighlightBackground)(track.nodePathInfo, {
56
+ hovered,
57
+ selectedBackground: TimelineSelection_1.TIMELINE_SELECTED_BACKGROUND,
58
+ });
56
59
  const layerStyle = (0, react_1.useMemo)(() => ({
57
60
  height: (0, timeline_layout_1.getTimelineLayerHeight)(track.sequence.type),
58
61
  marginBottom: timeline_layout_1.TIMELINE_ITEM_BORDER_BOTTOM,
@@ -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
  }>;