@remotion/studio 4.0.478 → 4.0.481

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 (201) hide show
  1. package/dist/components/AssetSelector.js +8 -14
  2. package/dist/components/AudioWaveform.js +19 -11
  3. package/dist/components/Button.d.ts +2 -0
  4. package/dist/components/Button.js +9 -6
  5. package/dist/components/CompactExplanation.d.ts +12 -0
  6. package/dist/components/CompactExplanation.js +52 -0
  7. package/dist/components/CompositionSelector.js +2 -4
  8. package/dist/components/CurrentAsset.d.ts +3 -1
  9. package/dist/components/CurrentAsset.js +42 -34
  10. package/dist/components/CurrentComposition.d.ts +1 -1
  11. package/dist/components/CurrentComposition.js +38 -31
  12. package/dist/components/CurrentCompositionSideEffects.d.ts +0 -3
  13. package/dist/components/CurrentCompositionSideEffects.js +1 -37
  14. package/dist/components/DefaultPropsEditor.d.ts +12 -2
  15. package/dist/components/DefaultPropsEditor.js +2 -2
  16. package/dist/components/Editor.js +2 -5
  17. package/dist/components/EditorContent.js +2 -1
  18. package/dist/components/EffectPickerModal.d.ts +5 -0
  19. package/dist/components/EffectPickerModal.js +179 -0
  20. package/dist/components/ExpandedTracksProvider.d.ts +1 -0
  21. package/dist/components/ExpandedTracksProvider.js +81 -7
  22. package/dist/components/GlobalKeybindings.d.ts +3 -1
  23. package/dist/components/GlobalKeybindings.js +104 -10
  24. package/dist/components/InspectorInfoHeader.d.ts +11 -0
  25. package/dist/components/InspectorInfoHeader.js +55 -0
  26. package/dist/components/InspectorPanel/DefaultInspector.d.ts +8 -0
  27. package/dist/components/InspectorPanel/DefaultInspector.js +93 -0
  28. package/dist/components/InspectorPanel/EasingInspector.d.ts +5 -0
  29. package/dist/components/InspectorPanel/EasingInspector.js +41 -0
  30. package/dist/components/InspectorPanel/GuideInspector.d.ts +7 -0
  31. package/dist/components/InspectorPanel/GuideInspector.js +55 -0
  32. package/dist/components/InspectorPanel/KeyframeInspector.d.ts +7 -0
  33. package/dist/components/InspectorPanel/KeyframeInspector.js +109 -0
  34. package/dist/components/InspectorPanel/SelectedInspector.d.ts +5 -0
  35. package/dist/components/InspectorPanel/SelectedInspector.js +26 -0
  36. package/dist/components/InspectorPanel/SequenceSelectionInspector.d.ts +5 -0
  37. package/dist/components/InspectorPanel/SequenceSelectionInspector.js +117 -0
  38. package/dist/components/InspectorPanel/common.d.ts +15 -0
  39. package/dist/components/InspectorPanel/common.js +18 -0
  40. package/dist/components/InspectorPanel/inspector-selection.d.ts +10 -0
  41. package/dist/components/InspectorPanel/inspector-selection.js +35 -0
  42. package/dist/components/InspectorPanel/styles.d.ts +28 -0
  43. package/dist/components/InspectorPanel/styles.js +196 -0
  44. package/dist/components/InspectorPanel/use-track-for-selection.d.ts +2 -0
  45. package/dist/components/InspectorPanel/use-track-for-selection.js +22 -0
  46. package/dist/components/InspectorPanel.d.ts +8 -0
  47. package/dist/components/InspectorPanel.js +26 -0
  48. package/dist/components/InspectorPanelLayout.d.ts +1 -0
  49. package/dist/components/InspectorPanelLayout.js +4 -0
  50. package/dist/components/InspectorSequenceSection.d.ts +19 -0
  51. package/dist/components/InspectorSequenceSection.js +157 -0
  52. package/dist/components/InspectorSourceLocation.d.ts +7 -0
  53. package/dist/components/InspectorSourceLocation.js +71 -0
  54. package/dist/components/KeyboardShortcutsExplainer.js +10 -2
  55. package/dist/components/Modals.js +3 -3
  56. package/dist/components/NewComposition/InputDragger.js +1 -1
  57. package/dist/components/NewComposition/RemInput.d.ts +1 -0
  58. package/dist/components/NewComposition/RemInput.js +8 -2
  59. package/dist/components/NewComposition/RemTextarea.d.ts +1 -0
  60. package/dist/components/NewComposition/RemTextarea.js +8 -2
  61. package/dist/components/NewComposition/ValidationMessage.d.ts +3 -0
  62. package/dist/components/NewComposition/ValidationMessage.js +16 -5
  63. package/dist/components/OptionsPanel.d.ts +1 -1
  64. package/dist/components/OptionsPanel.js +8 -17
  65. package/dist/components/QuickSwitcher/QuickSwitcherContent.js +2 -7
  66. package/dist/components/QuickSwitcher/QuickSwitcherResult.js +3 -10
  67. package/dist/components/QuickSwitcher/shared.d.ts +4 -0
  68. package/dist/components/QuickSwitcher/shared.js +24 -0
  69. package/dist/components/RenderModal/DataEditor.d.ts +29 -2
  70. package/dist/components/RenderModal/DataEditor.js +107 -56
  71. package/dist/components/RenderModal/RenderModalJSONPropsEditor.d.ts +1 -0
  72. package/dist/components/RenderModal/RenderModalJSONPropsEditor.js +25 -7
  73. package/dist/components/RenderModal/SchemaEditor/Fieldset.d.ts +2 -1
  74. package/dist/components/RenderModal/SchemaEditor/Fieldset.js +10 -5
  75. package/dist/components/RenderModal/SchemaEditor/SchemaEditor.d.ts +4 -0
  76. package/dist/components/RenderModal/SchemaEditor/SchemaEditor.js +27 -4
  77. package/dist/components/RenderModal/SchemaEditor/SchemaErrorMessages.d.ts +12 -4
  78. package/dist/components/RenderModal/SchemaEditor/SchemaErrorMessages.js +23 -9
  79. package/dist/components/RenderModal/SchemaEditor/SchemaLabel.js +3 -3
  80. package/dist/components/RenderModal/SchemaEditor/SchemaSeparationLine.js +8 -1
  81. package/dist/components/RenderModal/SchemaEditor/ZodColorEditor.js +1 -1
  82. package/dist/components/RenderModal/SchemaEditor/ZodDateEditor.js +1 -1
  83. package/dist/components/RenderModal/SchemaEditor/ZodDiscriminatedUnionEditor.js +1 -1
  84. package/dist/components/RenderModal/SchemaEditor/ZodEnumEditor.js +1 -1
  85. package/dist/components/RenderModal/SchemaEditor/ZodErrorMessages.d.ts +1 -0
  86. package/dist/components/RenderModal/SchemaEditor/ZodErrorMessages.js +23 -6
  87. package/dist/components/RenderModal/SchemaEditor/ZodFieldValidation.js +2 -2
  88. package/dist/components/RenderModal/SchemaEditor/ZodNonEditableValue.js +2 -1
  89. package/dist/components/RenderModal/SchemaEditor/ZodNumberEditor.js +1 -1
  90. package/dist/components/RenderModal/SchemaEditor/ZodObjectEditor.js +9 -11
  91. package/dist/components/RenderModal/SchemaEditor/ZodOrNullishEditor.js +1 -1
  92. package/dist/components/RenderModal/SchemaEditor/ZodStaticFileEditor.js +1 -1
  93. package/dist/components/RenderModal/SchemaEditor/ZodStringEditor.js +1 -1
  94. package/dist/components/RenderModal/SchemaEditor/ZodTextareaEditor.js +1 -1
  95. package/dist/components/RenderModal/WarningIndicatorButton.d.ts +1 -0
  96. package/dist/components/RenderModal/WarningIndicatorButton.js +17 -4
  97. package/dist/components/RenderModal/get-render-modal-warnings.d.ts +2 -1
  98. package/dist/components/RenderModal/get-render-modal-warnings.js +6 -3
  99. package/dist/components/RendersTab.js +1 -1
  100. package/dist/components/ResetZoomButton.d.ts +2 -1
  101. package/dist/components/ResetZoomButton.js +5 -1
  102. package/dist/components/SegmentedControl.d.ts +3 -0
  103. package/dist/components/SegmentedControl.js +11 -5
  104. package/dist/components/SelectedOutlineElement.js +96 -24
  105. package/dist/components/SelectedOutlineOverlay.d.ts +1 -1
  106. package/dist/components/SelectedOutlineOverlay.js +44 -30
  107. package/dist/components/SelectedOutlineUvControls.d.ts +9 -0
  108. package/dist/components/SelectedOutlineUvControls.js +64 -10
  109. package/dist/components/Tabs/index.js +4 -4
  110. package/dist/components/Timeline/EasingEditorModal.d.ts +5 -4
  111. package/dist/components/Timeline/EasingEditorModal.js +597 -124
  112. package/dist/components/Timeline/KeyframeSettingsModal.d.ts +2 -2
  113. package/dist/components/Timeline/SubscribeToNodePaths.d.ts +2 -2
  114. package/dist/components/Timeline/Timeline.js +9 -9
  115. package/dist/components/Timeline/TimelineClipboardKeybindings.d.ts +15 -3
  116. package/dist/components/Timeline/TimelineClipboardKeybindings.js +85 -1
  117. package/dist/components/Timeline/TimelineDeleteKeybindings.js +10 -3
  118. package/dist/components/Timeline/TimelineEffectItem.d.ts +2 -2
  119. package/dist/components/Timeline/TimelineEffectItem.js +1 -1
  120. package/dist/components/Timeline/TimelineEffectPropItem.d.ts +8 -0
  121. package/dist/components/Timeline/TimelineEffectPropItem.js +25 -21
  122. package/dist/components/Timeline/TimelineExpandArrowButton.js +42 -2
  123. package/dist/components/Timeline/TimelineExpandedRow.d.ts +5 -2
  124. package/dist/components/Timeline/TimelineExpandedRow.js +6 -6
  125. package/dist/components/Timeline/TimelineExpandedSection.d.ts +1 -1
  126. package/dist/components/Timeline/TimelineExpandedSection.js +10 -25
  127. package/dist/components/Timeline/TimelineKeyframeControls.d.ts +8 -2
  128. package/dist/components/Timeline/TimelineKeyframeControls.js +24 -3
  129. package/dist/components/Timeline/TimelineKeyframeEasingLine.js +2 -47
  130. package/dist/components/Timeline/TimelineKeyframedValue.d.ts +1 -1
  131. package/dist/components/Timeline/TimelineKeyframedValue.js +8 -10
  132. package/dist/components/Timeline/TimelineNumberField.js +5 -11
  133. package/dist/components/Timeline/TimelineRotationField.js +5 -6
  134. package/dist/components/Timeline/TimelineRowChrome.d.ts +2 -0
  135. package/dist/components/Timeline/TimelineRowChrome.js +5 -3
  136. package/dist/components/Timeline/TimelineScaleField.js +4 -8
  137. package/dist/components/Timeline/TimelineSelection.d.ts +28 -2
  138. package/dist/components/Timeline/TimelineSelection.js +342 -61
  139. package/dist/components/Timeline/TimelineSequence.js +19 -3
  140. package/dist/components/Timeline/TimelineSequenceItem.js +68 -64
  141. package/dist/components/Timeline/TimelineSequencePropItem.d.ts +12 -2
  142. package/dist/components/Timeline/TimelineSequencePropItem.js +57 -53
  143. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +6 -4
  144. package/dist/components/Timeline/TimelineTransformOriginField.js +4 -5
  145. package/dist/components/Timeline/TimelineTranslateField.js +4 -5
  146. package/dist/components/Timeline/TimelineUvCoordinateField.js +4 -4
  147. package/dist/components/Timeline/call-add-keyframe.d.ts +4 -4
  148. package/dist/components/Timeline/call-delete-keyframe.d.ts +4 -4
  149. package/dist/components/Timeline/call-move-keyframe.d.ts +2 -2
  150. package/dist/components/Timeline/call-update-keyframe-settings.d.ts +3 -3
  151. package/dist/components/Timeline/delete-selected-timeline-item.d.ts +2 -1
  152. package/dist/components/Timeline/delete-selected-timeline-item.js +27 -1
  153. package/dist/components/Timeline/find-track-for-node-path-info.js +2 -2
  154. package/dist/components/Timeline/get-node-keyframes.d.ts +7 -0
  155. package/dist/components/Timeline/get-node-keyframes.js +26 -1
  156. package/dist/components/Timeline/parse-keyframe-field-from-node-path.js +2 -2
  157. package/dist/components/Timeline/reset-selected-timeline-props.d.ts +3 -3
  158. package/dist/components/Timeline/reset-selected-timeline-props.js +34 -7
  159. package/dist/components/Timeline/save-effect-prop.d.ts +2 -2
  160. package/dist/components/Timeline/save-sequence-prop.d.ts +2 -2
  161. package/dist/components/Timeline/sequence-props-subscription-store.d.ts +3 -3
  162. package/dist/components/Timeline/timeline-expanded-filter.d.ts +12 -0
  163. package/dist/components/Timeline/timeline-expanded-filter.js +38 -0
  164. package/dist/components/Timeline/timeline-field-display-utils.d.ts +5 -0
  165. package/dist/components/Timeline/timeline-field-display-utils.js +244 -0
  166. package/dist/components/Timeline/update-selected-easing.d.ts +47 -4
  167. package/dist/components/Timeline/update-selected-easing.js +40 -9
  168. package/dist/components/Timeline/use-expanded-track-keyframe-rows.js +50 -18
  169. package/dist/components/Timeline/use-sequence-freeze-frame-menu-item.d.ts +13 -0
  170. package/dist/components/Timeline/use-sequence-freeze-frame-menu-item.js +73 -0
  171. package/dist/components/Timeline/use-sequence-props-subscription.d.ts +3 -3
  172. package/dist/components/Timeline/use-timeline-expanded-tree.d.ts +12 -0
  173. package/dist/components/Timeline/use-timeline-expanded-tree.js +60 -0
  174. package/dist/components/Timeline/use-timeline-height.js +51 -7
  175. package/dist/components/Timeline/use-timeline-keyframe-drag.js +12 -6
  176. package/dist/components/TopPanel.js +1 -1
  177. package/dist/components/VisualControls/VisualControlsContent.d.ts +1 -1
  178. package/dist/components/VisualControls/VisualControlsContent.js +4 -5
  179. package/dist/components/effect-drag-and-drop.d.ts +10 -0
  180. package/dist/components/effect-drag-and-drop.js +17 -8
  181. package/dist/components/effect-picker-search.d.ts +5 -0
  182. package/dist/components/effect-picker-search.js +77 -0
  183. package/dist/components/selected-outline-drag.d.ts +21 -2
  184. package/dist/components/selected-outline-drag.js +31 -6
  185. package/dist/components/selected-outline-measurement.js +48 -14
  186. package/dist/components/selected-outline-types.d.ts +7 -7
  187. package/dist/components/selected-outline-uv.d.ts +4 -3
  188. package/dist/components/selected-outline-uv.js +6 -2
  189. package/dist/error-overlay/remotion-overlay/ErrorLoader.js +8 -1
  190. package/dist/esm/{chunk-hrw9799x.js → chunk-4rq5gt8c.js} +30557 -26640
  191. package/dist/esm/internals.mjs +30557 -26640
  192. package/dist/esm/previewEntry.mjs +18584 -14665
  193. package/dist/esm/renderEntry.mjs +1 -1
  194. package/dist/helpers/migrate-expanded-tracks-for-subscription-key.js +3 -3
  195. package/dist/helpers/render-codec-label.d.ts +2 -0
  196. package/dist/helpers/render-codec-label.js +49 -0
  197. package/dist/helpers/timeline-layout.d.ts +4 -4
  198. package/dist/helpers/use-media-metadata.d.ts +8 -2
  199. package/dist/helpers/use-media-metadata.js +17 -4
  200. package/dist/state/modals.d.ts +9 -4
  201. package/package.json +12 -12
@@ -62,6 +62,7 @@ const TimelineSequenceRightEdgeDragHandle_1 = require("./TimelineSequenceRightEd
62
62
  const TimelineVideoInfo_1 = require("./TimelineVideoInfo");
63
63
  const TimelineWidthProvider_1 = require("./TimelineWidthProvider");
64
64
  const use_resolved_stack_react_to_change_1 = require("./use-resolved-stack-react-to-change");
65
+ const use_sequence_freeze_frame_menu_item_1 = require("./use-sequence-freeze-frame-menu-item");
65
66
  const AUDIO_GRADIENT = 'linear-gradient(rgb(16 171 58), rgb(43 165 63) 60%)';
66
67
  const VIDEO_GRADIENT = 'linear-gradient(to top, #8e44ad, #9b59b6)';
67
68
  const IMAGE_GRADIENT = 'linear-gradient(to top, #2980b9, #3498db)';
@@ -154,7 +155,7 @@ const TimelineSequenceInner = ({ s, windowWidth, nodePathInfo, sequenceFrameOffs
154
155
  // Some compositions may not be longer than their media duration,
155
156
  // if that is the case, it needs to be asynchronously determined
156
157
  var _a, _b;
157
- var _c, _d, _e, _f;
158
+ var _c, _d, _e, _f, _g;
158
159
  const video = remotion_1.Internals.useVideo();
159
160
  const maxMediaDuration = (0, use_max_media_duration_1.useMaxMediaDuration)(s, (_c = video === null || video === void 0 ? void 0 : video.fps) !== null && _c !== void 0 ? _c : 30);
160
161
  const effectiveMaxMediaDuration = s.loopDisplay ? null : maxMediaDuration;
@@ -184,6 +185,7 @@ const TimelineSequenceInner = ({ s, windowWidth, nodePathInfo, sequenceFrameOffs
184
185
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
185
186
  const previewConnected = previewServerState.type === 'connected';
186
187
  const { setPropStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
188
+ const timelinePosition = remotion_1.Internals.Timeline.useTimelinePosition();
187
189
  const selectAsset = (0, use_select_asset_1.useSelectAsset)();
188
190
  const confirm = (0, ConfirmationDialog_1.useConfirmationDialog)();
189
191
  const { onSelect, selectable } = (0, TimelineSelection_1.useTimelineRowSelection)(nodePathInfo);
@@ -279,6 +281,18 @@ const TimelineSequenceInner = ({ s, windowWidth, nodePathInfo, sequenceFrameOffs
279
281
  setPropStatuses,
280
282
  validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source,
281
283
  ]);
284
+ const freezeFrameMenuItem = (0, use_sequence_freeze_frame_menu_item_1.useSequenceFreezeFrameMenuItem)({
285
+ clientId: previewServerState.type === 'connected'
286
+ ? previewServerState.clientId
287
+ : null,
288
+ nodePath,
289
+ propStatusesForOverride,
290
+ sequence: s,
291
+ sequenceFrameOffset,
292
+ setPropStatuses,
293
+ timelinePosition,
294
+ validatedSource: (_e = validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source) !== null && _e !== void 0 ? _e : null,
295
+ });
282
296
  const contextMenuValues = (0, react_1.useMemo)(() => {
283
297
  if (!previewConnected) {
284
298
  return [];
@@ -298,6 +312,7 @@ const TimelineSequenceInner = ({ s, windowWidth, nodePathInfo, sequenceFrameOffs
298
312
  originalLocation,
299
313
  selectAsset,
300
314
  sequence: s,
315
+ sourceActions: [freezeFrameMenuItem],
301
316
  });
302
317
  }, [
303
318
  assetLinkInfo,
@@ -306,6 +321,7 @@ const TimelineSequenceInner = ({ s, windowWidth, nodePathInfo, sequenceFrameOffs
306
321
  disableInteractivityDisabled,
307
322
  duplicateDisabled,
308
323
  fileLocation,
324
+ freezeFrameMenuItem,
309
325
  onDeleteSequenceFromSource,
310
326
  onDisableSequenceInteractivity,
311
327
  onDuplicateSequenceFromSource,
@@ -324,7 +340,7 @@ const TimelineSequenceInner = ({ s, windowWidth, nodePathInfo, sequenceFrameOffs
324
340
  const { onPointerDown: onMoveDragPointerDown } = (0, TimelineSequenceRightEdgeDragHandle_1.useTimelineSequenceFromDrag)({
325
341
  nodePathInfo,
326
342
  windowWidth,
327
- timelineDurationInFrames: (_e = video === null || video === void 0 ? void 0 : video.durationInFrames) !== null && _e !== void 0 ? _e : 1,
343
+ timelineDurationInFrames: (_f = video === null || video === void 0 ? void 0 : video.durationInFrames) !== null && _f !== void 0 ? _f : 1,
328
344
  });
329
345
  if (!video) {
330
346
  throw new TypeError('Expected video config');
@@ -378,7 +394,7 @@ const TimelineSequenceInner = ({ s, windowWidth, nodePathInfo, sequenceFrameOffs
378
394
  if (maxMediaDuration === null && !s.loopDisplay) {
379
395
  return null;
380
396
  }
381
- const sequence = (jsx_runtime_1.jsxs(TimelineSequenceCurrentFrame, { s: s, displayDurationInFrames: displayDurationInFrames, premountWidth: premountWidth, postmountWidth: postmountWidth, style: style, nodePathInfo: nodePathInfo, sequenceFrameOffset: sequenceFrameOffset, fromCanUpdate: fromCanUpdate, frozenFrame: frozenFrame, onMoveDragPointerDown: onMoveDragPointerDown, children: [s.type === 'audio' ? (jsx_runtime_1.jsx(AudioWaveform_1.AudioWaveform, { src: s.src, height: timeline_layout_1.TIMELINE_LAYER_HEIGHT_AUDIO, doesVolumeChange: s.doesVolumeChange, visualizationWidth: width, startFrom: s.startMediaFrom, durationInFrames: s.duration, volume: s.volume, playbackRate: s.playbackRate, loopDisplay: s.loopDisplay })) : null, s.type === 'video' ? (jsx_runtime_1.jsx(TimelineVideoInfo_1.TimelineVideoInfo, { src: s.src, visualizationWidth: width, naturalWidth: naturalWidth, trimBefore: s.startMediaFrom, durationInFrames: s.duration, playbackRate: s.playbackRate, volume: s.volume, doesVolumeChange: s.doesVolumeChange, premountWidth: premountWidth !== null && premountWidth !== void 0 ? premountWidth : 0, postmountWidth: postmountWidth !== null && postmountWidth !== void 0 ? postmountWidth : 0, loopDisplay: s.loopDisplay, frozenMediaFrame: s.frozenMediaFrame })) : null, s.type === 'image' ? (jsx_runtime_1.jsx(TimelineImageInfo_1.TimelineImageInfo, { src: s.src, visualizationWidth: width })) : null, s.loopDisplay === undefined ? null : (jsx_runtime_1.jsx(LoopedTimelineIndicators_1.LoopedTimelineIndicator, { loops: s.loopDisplay.numberOfTimes })), showRightEdgeDragHandle && nodePathInfo && validatedLocation ? (jsx_runtime_1.jsx(TimelineSequenceRightEdgeDragHandle_1.TimelineSequenceRightEdgeDragHandle, { nodePathInfo: nodePathInfo, windowWidth: windowWidth, timelineDurationInFrames: (_f = video.durationInFrames) !== null && _f !== void 0 ? _f : 1 })) : null] }));
397
+ const sequence = (jsx_runtime_1.jsxs(TimelineSequenceCurrentFrame, { s: s, displayDurationInFrames: displayDurationInFrames, premountWidth: premountWidth, postmountWidth: postmountWidth, style: style, nodePathInfo: nodePathInfo, sequenceFrameOffset: sequenceFrameOffset, fromCanUpdate: fromCanUpdate, frozenFrame: frozenFrame, onMoveDragPointerDown: onMoveDragPointerDown, children: [s.type === 'audio' ? (jsx_runtime_1.jsx(AudioWaveform_1.AudioWaveform, { src: s.src, height: timeline_layout_1.TIMELINE_LAYER_HEIGHT_AUDIO, doesVolumeChange: s.doesVolumeChange, visualizationWidth: width, startFrom: s.startMediaFrom, durationInFrames: s.duration, volume: s.volume, playbackRate: s.playbackRate, loopDisplay: s.loopDisplay })) : null, s.type === 'video' ? (jsx_runtime_1.jsx(TimelineVideoInfo_1.TimelineVideoInfo, { src: s.src, visualizationWidth: width, naturalWidth: naturalWidth, trimBefore: s.startMediaFrom, durationInFrames: s.duration, playbackRate: s.playbackRate, volume: s.volume, doesVolumeChange: s.doesVolumeChange, premountWidth: premountWidth !== null && premountWidth !== void 0 ? premountWidth : 0, postmountWidth: postmountWidth !== null && postmountWidth !== void 0 ? postmountWidth : 0, loopDisplay: s.loopDisplay, frozenMediaFrame: s.frozenMediaFrame })) : null, s.type === 'image' ? (jsx_runtime_1.jsx(TimelineImageInfo_1.TimelineImageInfo, { src: s.src, visualizationWidth: width })) : null, s.loopDisplay === undefined ? null : (jsx_runtime_1.jsx(LoopedTimelineIndicators_1.LoopedTimelineIndicator, { loops: s.loopDisplay.numberOfTimes })), showRightEdgeDragHandle && nodePathInfo && validatedLocation ? (jsx_runtime_1.jsx(TimelineSequenceRightEdgeDragHandle_1.TimelineSequenceRightEdgeDragHandle, { nodePathInfo: nodePathInfo, windowWidth: windowWidth, timelineDurationInFrames: (_g = video.durationInFrames) !== null && _g !== void 0 ? _g : 1 })) : null] }));
382
398
  return previewConnected ? (jsx_runtime_1.jsx(ContextMenu_1.ContextMenu, { values: contextMenuValues, onOpen: onContextMenuOpen, children: sequence })) : (sequence);
383
399
  };
384
400
  exports.TimelineSequence = react_1.default.memo(TimelineSequenceFn);
@@ -41,6 +41,7 @@ const client_id_1 = require("../../helpers/client-id");
41
41
  const format_file_location_1 = require("../../helpers/format-file-location");
42
42
  const timeline_layout_1 = require("../../helpers/timeline-layout");
43
43
  const use_keybinding_1 = require("../../helpers/use-keybinding");
44
+ const modals_1 = require("../../state/modals");
44
45
  const call_api_1 = require("../call-api");
45
46
  const ConfirmationDialog_1 = require("../ConfirmationDialog");
46
47
  const ContextMenu_1 = require("../ContextMenu");
@@ -63,6 +64,8 @@ const TimelineRowChrome_1 = require("./TimelineRowChrome");
63
64
  const TimelineSelection_1 = require("./TimelineSelection");
64
65
  const TimelineSequenceName_1 = require("./TimelineSequenceName");
65
66
  const use_open_sequence_in_editor_1 = require("./use-open-sequence-in-editor");
67
+ const use_sequence_freeze_frame_menu_item_1 = require("./use-sequence-freeze-frame-menu-item");
68
+ const use_timeline_expanded_tree_1 = require("./use-timeline-expanded-tree");
66
69
  const labelContainerStyle = {
67
70
  alignItems: 'center',
68
71
  alignSelf: 'stretch',
@@ -77,6 +80,16 @@ const effectDropHighlight = {
77
80
  };
78
81
  const SEQUENCE_REORDER_MIME_TYPE = 'application/remotion-sequence-reorder';
79
82
  let currentSequenceDrag = null;
83
+ const TimelineSequenceExpandArrow = ({ disabled, isExpanded, nodePathInfo, onToggleExpand, sequence }) => {
84
+ const { filteredTree } = (0, use_timeline_expanded_tree_1.useTimelineExpandedTree)({
85
+ sequence,
86
+ nodePathInfo,
87
+ });
88
+ if (filteredTree.length === 0) {
89
+ return jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowSpacer, {});
90
+ }
91
+ return (jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowButton, { isExpanded: isExpanded, onClick: onToggleExpand, label: "track properties", disabled: disabled }));
92
+ };
80
93
  const sequenceReorderWrapper = {
81
94
  position: 'relative',
82
95
  };
@@ -139,7 +152,7 @@ const getDestinationIndex = ({ fromIndex, insertionIndex, }) => {
139
152
  };
140
153
  const TimelineSequenceItem = ({ nestedDepth, sequence, nodePathInfo, keyframeDisplayOffset, sequenceFrameOffset, trackIndex, }) => {
141
154
  var _a, _b, _c;
142
- var _d, _e;
155
+ var _d, _e, _f;
143
156
  const nodePath = (_d = nodePathInfo === null || nodePathInfo === void 0 ? void 0 : nodePathInfo.sequenceSubscriptionKey) !== null && _d !== void 0 ? _d : null;
144
157
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
145
158
  const previewConnected = previewServerState.type === 'connected';
@@ -147,9 +160,10 @@ const TimelineSequenceItem = ({ nestedDepth, sequence, nodePathInfo, keyframeDis
147
160
  const { toggleTrack } = (0, react_1.useContext)(ExpandedTracksProvider_1.ExpandedTracksSetterContext);
148
161
  const { propStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModePropStatusesContext);
149
162
  const { setPropStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
163
+ const { setSelectedModal } = (0, react_1.useContext)(modals_1.ModalsContext);
150
164
  const { isHighestContext } = (0, use_keybinding_1.useKeybinding)();
151
165
  const selectAsset = (0, use_select_asset_1.useSelectAsset)();
152
- const { onSelect, selectable, selected } = (0, TimelineSelection_1.useTimelineRowSelection)(nodePathInfo);
166
+ const { onSelect, selectable, selected, selectionItem } = (0, TimelineSelection_1.useTimelineRowSelection)(nodePathInfo);
153
167
  const { selectedItems } = (0, TimelineSelection_1.useTimelineSelection)();
154
168
  const containsSelection = (0, TimelineSelection_1.useTimelineRowContainsSelection)(nodePathInfo);
155
169
  const [effectDropHovered, setEffectDropHovered] = (0, react_1.useState)(false);
@@ -616,58 +630,40 @@ const TimelineSequenceItem = ({ nestedDepth, sequence, nodePathInfo, keyframeDis
616
630
  }
617
631
  setIsRenaming(true);
618
632
  }, [canRenameThisSequence]);
619
- const freezeStatus = propStatusesForOverride === null || propStatusesForOverride === void 0 ? void 0 : propStatusesForOverride.freeze;
620
- const isFrozen = (freezeStatus === null || freezeStatus === void 0 ? void 0 : freezeStatus.status) === 'static' &&
621
- typeof freezeStatus.codeValue === 'number';
622
- const canToggleFreeze = previewConnected &&
623
- Boolean(sequence.controls) &&
624
- nodePath !== null &&
625
- validatedLocation !== null &&
626
- freezeStatus !== undefined &&
627
- freezeStatus !== null &&
628
- freezeStatus.status === 'static';
629
- const onToggleFreezeFrame = (0, react_1.useCallback)(() => {
630
- if (!canToggleFreeze ||
631
- !sequence.controls ||
633
+ const freezeFrameMenuItem = (0, use_sequence_freeze_frame_menu_item_1.useSequenceFreezeFrameMenuItem)({
634
+ clientId: previewServerState.type === 'connected'
635
+ ? previewServerState.clientId
636
+ : null,
637
+ nodePath,
638
+ propStatusesForOverride,
639
+ sequence,
640
+ sequenceFrameOffset,
641
+ setPropStatuses,
642
+ timelinePosition,
643
+ validatedSource: (_f = validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source) !== null && _f !== void 0 ? _f : null,
644
+ });
645
+ const canAddEffect = (nodePathInfo === null || nodePathInfo === void 0 ? void 0 : nodePathInfo.supportsEffects) === true &&
646
+ previewServerState.type === 'connected' &&
647
+ Boolean(validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source);
648
+ const onAddEffect = (0, react_1.useCallback)(() => {
649
+ if (!canAddEffect ||
650
+ previewServerState.type !== 'connected' ||
632
651
  !nodePath ||
633
- !validatedLocation ||
634
- previewServerState.type !== 'connected') {
652
+ !(validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source)) {
635
653
  return;
636
654
  }
637
- const rawFreezeFrame = Math.round(timelinePosition - sequence.from + sequenceFrameOffset);
638
- const maxFrame = Number.isFinite(sequence.duration)
639
- ? Math.max(0, sequence.duration - 1)
640
- : rawFreezeFrame;
641
- const freezeFrame = Math.min(Math.max(0, rawFreezeFrame), maxFrame);
642
- const remove = isFrozen;
643
- (0, save_sequence_prop_1.saveSequenceProps)({
644
- changes: [
645
- {
646
- fileName: validatedLocation.source,
647
- nodePath,
648
- fieldKey: 'freeze',
649
- value: remove ? null : freezeFrame,
650
- defaultValue: null,
651
- schema: sequence.controls.schema,
652
- },
653
- ],
654
- setPropStatuses,
655
+ setSelectedModal({
656
+ type: 'add-effect',
655
657
  clientId: previewServerState.clientId,
656
- undoLabel: remove ? 'Unfreeze sequence' : 'Freeze sequence',
657
- redoLabel: remove ? 'Freeze sequence again' : 'Unfreeze sequence again',
658
+ fileName: validatedLocation.source,
659
+ nodePath,
658
660
  });
659
661
  }, [
660
- canToggleFreeze,
661
- isFrozen,
662
+ canAddEffect,
662
663
  nodePath,
663
664
  previewServerState,
664
- sequence.controls,
665
- sequence.duration,
666
- sequence.from,
667
- sequenceFrameOffset,
668
- setPropStatuses,
669
- timelinePosition,
670
- validatedLocation,
665
+ setSelectedModal,
666
+ validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source,
671
667
  ]);
672
668
  const contextMenuValues = (0, react_1.useMemo)(() => {
673
669
  if (!previewConnected) {
@@ -689,6 +685,26 @@ const TimelineSequenceItem = ({ nestedDepth, sequence, nodePathInfo, keyframeDis
689
685
  selectAsset,
690
686
  sequence,
691
687
  sourceActions: [
688
+ ...((nodePathInfo === null || nodePathInfo === void 0 ? void 0 : nodePathInfo.supportsEffects)
689
+ ? [
690
+ {
691
+ type: 'item',
692
+ id: 'add-effect',
693
+ keyHint: null,
694
+ label: 'Add effect...',
695
+ leftItem: null,
696
+ disabled: !canAddEffect,
697
+ onClick: onAddEffect,
698
+ quickSwitcherLabel: null,
699
+ subMenu: null,
700
+ value: 'add-effect',
701
+ },
702
+ {
703
+ type: 'divider',
704
+ id: 'add-effect-divider',
705
+ },
706
+ ]
707
+ : []),
692
708
  {
693
709
  type: 'item',
694
710
  id: 'rename-sequence',
@@ -703,37 +719,25 @@ const TimelineSequenceItem = ({ nestedDepth, sequence, nodePathInfo, keyframeDis
703
719
  subMenu: null,
704
720
  value: 'rename-sequence',
705
721
  },
706
- {
707
- type: 'item',
708
- id: 'toggle-freeze-frame',
709
- keyHint: null,
710
- label: isFrozen ? 'Unfreeze frame' : 'Freeze frame',
711
- leftItem: null,
712
- disabled: !canToggleFreeze,
713
- onClick: () => {
714
- onToggleFreezeFrame();
715
- },
716
- quickSwitcherLabel: null,
717
- subMenu: null,
718
- value: 'toggle-freeze-frame',
719
- },
722
+ freezeFrameMenuItem,
720
723
  ],
721
724
  });
722
725
  }, [
723
726
  assetLinkInfo,
727
+ canAddEffect,
724
728
  canOpenInEditor,
725
729
  canRenameThisSequence,
726
- canToggleFreeze,
727
730
  deleteDisabled,
728
731
  disableInteractivityDisabled,
729
732
  duplicateDisabled,
730
733
  fileLocation,
731
- isFrozen,
734
+ freezeFrameMenuItem,
735
+ nodePathInfo === null || nodePathInfo === void 0 ? void 0 : nodePathInfo.supportsEffects,
736
+ onAddEffect,
732
737
  onDeleteSequenceFromSource,
733
738
  onDisableSequenceInteractivity,
734
739
  onDuplicateSequenceFromSource,
735
740
  onRenameSequence,
736
- onToggleFreezeFrame,
737
741
  openInEditor,
738
742
  originalLocation,
739
743
  previewConnected,
@@ -798,7 +802,7 @@ const TimelineSequenceItem = ({ nestedDepth, sequence, nodePathInfo, keyframeDis
798
802
  clientId: previewServerState.clientId,
799
803
  });
800
804
  }, [canDropEffect, nodePath, previewServerState, validatedLocation]);
801
- 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 ? (jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowButton, { isExpanded: isExpanded, onClick: onToggleExpand, label: "track properties", disabled: !previewConnected || nodePathInfo === null })) : (jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowSpacer, {})), style: rowStyle, selected: selected, selectable: selectable, onSelect: onSelect, showSelectedBackground: true, containsSelection: containsSelection, outerHeight: outerHeight, onDragLeave: canDropEffect ? onEffectDragLeave : undefined, onDragOver: canDropEffect ? onEffectDragOver : undefined, onDrop: canDropEffect ? onEffectDrop : undefined, onDoubleClick: canOpenInEditor ? onShowInEditorDoubleClick : undefined, children: jsx_runtime_1.jsxs("div", { style: labelContainerStyle, children: [
805
+ 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: !previewConnected, isExpanded: isExpanded, nodePathInfo: nodePathInfo, onToggleExpand: onToggleExpand, sequence: sequence })) : (jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowSpacer, {})), style: rowStyle, selected: selected, selectable: selectable, selectionItem: selectionItem, onSelect: onSelect, showSelectedBackground: true, containsSelection: containsSelection, outerHeight: outerHeight, onDragLeave: canDropEffect ? onEffectDragLeave : undefined, onDragOver: canDropEffect ? onEffectDragOver : undefined, onDrop: canDropEffect ? onEffectDrop : undefined, onDoubleClick: canOpenInEditor ? onShowInEditorDoubleClick : undefined, children: jsx_runtime_1.jsxs("div", { style: labelContainerStyle, children: [
802
806
  jsx_runtime_1.jsx(TimelineSequenceName_1.TimelineSequenceName, { displayName: displayName, selected: selected, containsSelection: containsSelection, editing: isRenaming, onCancelEditing: onCancelRenaming, onSaveName: onSaveName }), mediaSrc ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
803
807
  jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }),
804
808
  " ",
@@ -1,14 +1,24 @@
1
1
  import React from 'react';
2
- import type { SequencePropsSubscriptionKey, SequenceSchema } from 'remotion';
2
+ import type { CanUpdateSequencePropStatusKeyframed, SequencePropsSubscriptionKey, InteractivitySchema } from 'remotion';
3
3
  import type { CodePosition } from '../../error-overlay/react-overlay/utils/get-source-map';
4
4
  import type { SequenceNodePathInfo } from '../../helpers/get-timeline-sequence-sort-key';
5
5
  import type { SchemaFieldInfo } from '../../helpers/timeline-layout';
6
+ import { type TimelineKeyframeControlsMode } from './TimelineKeyframeControls';
7
+ export declare const TimelineSequenceKeyframedValue: React.FC<{
8
+ readonly field: SchemaFieldInfo;
9
+ readonly fileName: string;
10
+ readonly nodePath: SequencePropsSubscriptionKey;
11
+ readonly schema: InteractivitySchema;
12
+ readonly propStatus: CanUpdateSequencePropStatusKeyframed;
13
+ readonly sourceFrame: number;
14
+ }>;
6
15
  export declare const TimelineSequencePropItem: React.FC<{
7
16
  readonly field: SchemaFieldInfo;
8
17
  readonly validatedLocation: CodePosition;
9
18
  readonly rowDepth: number;
10
19
  readonly nodePath: SequencePropsSubscriptionKey;
11
20
  readonly nodePathInfo: SequenceNodePathInfo;
12
- readonly schema: SequenceSchema;
21
+ readonly schema: InteractivitySchema;
13
22
  readonly keyframeDisplayOffset: number;
23
+ readonly keyframeControlsMode?: TimelineKeyframeControlsMode;
14
24
  }>;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TimelineSequencePropItem = void 0;
3
+ exports.TimelineSequencePropItem = exports.TimelineSequenceKeyframedValue = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const studio_shared_1 = require("@remotion/studio-shared");
6
6
  const react_1 = require("react");
@@ -115,34 +115,73 @@ const Value = ({ field, nodePath, validatedLocation, schema, propStatus }) => {
115
115
  }, [clearDragOverrides, nodePath]);
116
116
  return (jsx_runtime_1.jsx(TimelineSchemaField_1.TimelineFieldValue, { field: field, propStatus: propStatus, onSave: onSave, onDragValueChange: onDragValueChange, onDragEnd: onDragEnd, effectiveValue: effectiveValue, scaleLockNodePath: nodePath }));
117
117
  };
118
- const TimelineSequencePropItem = ({ field, validatedLocation, rowDepth, nodePath, nodePathInfo, schema, keyframeDisplayOffset, }) => {
119
- var _a, _b;
120
- const { propStatuses: visualModePropStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModePropStatusesContext);
118
+ const TimelineSequenceKeyframedValue = ({ field, fileName, nodePath, schema, propStatus, sourceFrame }) => {
121
119
  const { getDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeDragOverridesContext);
122
120
  const { setPropStatuses, setDragOverrides, clearDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
123
121
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
124
- const { setSelectedModal } = (0, react_1.useContext)(modals_1.ModalsContext);
125
- const selection = (0, TimelineSelection_1.useTimelineRowSelection)(nodePathInfo);
126
122
  const clientId = previewServerState.type === 'connected'
127
123
  ? previewServerState.clientId
128
124
  : null;
125
+ const dragOverrideValue = (0, react_1.useMemo)(() => {
126
+ var _a;
127
+ return ((_a = getDragOverrides(nodePath)) !== null && _a !== void 0 ? _a : {})[field.key];
128
+ }, [getDragOverrides, nodePath, field.key]);
129
+ const onSaveKeyframed = (0, react_1.useCallback)((value, frame) => {
130
+ if (!clientId) {
131
+ return Promise.reject(new Error('Not connected to studio server'));
132
+ }
133
+ return (0, call_add_keyframe_1.callAddSequenceKeyframe)({
134
+ fileName,
135
+ nodePath,
136
+ fieldKey: field.key,
137
+ sourceFrame: frame,
138
+ value,
139
+ schema,
140
+ setPropStatuses,
141
+ clientId,
142
+ });
143
+ }, [clientId, field.key, fileName, nodePath, schema, setPropStatuses]);
144
+ const onKeyframedDragValueChange = (0, react_1.useCallback)((value) => {
145
+ setDragOverrides(nodePath, field.key, remotion_1.Internals.makeKeyframedDragOverride({
146
+ status: propStatus,
147
+ frame: sourceFrame,
148
+ value,
149
+ }));
150
+ }, [propStatus, field.key, nodePath, setDragOverrides, sourceFrame]);
151
+ const onKeyframedDragEnd = (0, react_1.useCallback)(() => {
152
+ clearDragOverrides(nodePath);
153
+ }, [clearDragOverrides, nodePath]);
154
+ return (jsx_runtime_1.jsx(TimelineKeyframedValue_1.TimelineKeyframedValue, { field: field, propStatus: propStatus, sourceFrame: sourceFrame, dragOverrideValue: dragOverrideValue, onSave: onSaveKeyframed, onDragValueChange: onKeyframedDragValueChange, onDragEnd: onKeyframedDragEnd, scaleLockNodePath: nodePath }));
155
+ };
156
+ exports.TimelineSequenceKeyframedValue = TimelineSequenceKeyframedValue;
157
+ const TimelineSequencePropItem = ({ field, validatedLocation, rowDepth, nodePath, nodePathInfo, schema, keyframeDisplayOffset, keyframeControlsMode = 'timeline', }) => {
158
+ var _a, _b;
159
+ const { propStatuses: visualModePropStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModePropStatusesContext);
160
+ const { getDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeDragOverridesContext);
161
+ const { setPropStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
162
+ const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
163
+ const { setSelectedModal } = (0, react_1.useContext)(modals_1.ModalsContext);
164
+ const selection = (0, TimelineSelection_1.useTimelineRowSelection)(nodePathInfo);
165
+ const timelinePosition = remotion_1.Internals.Timeline.useTimelinePosition();
166
+ const sourceFrame = timelinePosition - keyframeDisplayOffset;
129
167
  const propStatusesForOverride = remotion_1.Internals.getPropStatusesCtx(visualModePropStatuses, nodePath);
130
168
  const propStatus = (_a = propStatusesForOverride === null || propStatusesForOverride === void 0 ? void 0 : propStatusesForOverride[field.key]) !== null && _a !== void 0 ? _a : null;
131
- const timelinePosition = remotion_1.Internals.Timeline.useTimelinePosition();
132
- const jsxFrame = timelinePosition - keyframeDisplayOffset;
133
169
  const dragOverrideValue = (0, react_1.useMemo)(() => {
134
170
  var _a;
135
171
  return ((_a = getDragOverrides(nodePath)) !== null && _a !== void 0 ? _a : {})[field.key];
136
172
  }, [getDragOverrides, nodePath, field.key]);
173
+ const keyframable = (0, studio_shared_1.isSchemaFieldKeyframable)({
174
+ schema,
175
+ key: field.key,
176
+ });
137
177
  const keyframeControls = propStatus !== null &&
138
- (0, TimelineKeyframeControls_1.shouldShowTimelineKeyframeControls)({
139
- propStatus,
140
- selected: selection.selected,
141
- keyframable: (0, studio_shared_1.isSchemaFieldKeyframable)({
142
- schema,
143
- key: field.key,
144
- }),
145
- }) ? (jsx_runtime_1.jsx(TimelineKeyframeControls_1.TimelineKeyframeControls, { fieldKey: field.key, propStatus: propStatus, nodePath: nodePath, fileName: validatedLocation.source, keyframeDisplayOffset: keyframeDisplayOffset, defaultValue: field.fieldSchema.default, dragOverrideValue: dragOverrideValue, schema: schema, effectIndex: null, nodePathInfo: nodePathInfo })) : null;
178
+ (keyframeControlsMode === 'inspector'
179
+ ? keyframable
180
+ : (0, TimelineKeyframeControls_1.shouldShowTimelineKeyframeControls)({
181
+ propStatus,
182
+ selected: selection.selected,
183
+ keyframable,
184
+ })) ? (jsx_runtime_1.jsx(TimelineKeyframeControls_1.TimelineKeyframeControls, { fieldKey: field.key, propStatus: propStatus, nodePath: nodePath, fileName: validatedLocation.source, keyframeDisplayOffset: keyframeDisplayOffset, defaultValue: field.fieldSchema.default, dragOverrideValue: dragOverrideValue, schema: schema, effectIndex: null, nodePathInfo: nodePathInfo, mode: keyframeControlsMode })) : null;
146
185
  const style = (0, react_1.useMemo)(() => {
147
186
  return {
148
187
  ...fieldRowBase,
@@ -203,41 +242,6 @@ const TimelineSequencePropItem = ({ field, validatedLocation, rowDepth, nodePath
203
242
  validatedLocation.source,
204
243
  propStatus,
205
244
  ]);
206
- const onSaveKeyframed = (0, react_1.useCallback)((value, sourceFrame) => {
207
- if (!clientId) {
208
- return Promise.reject(new Error('Not connected to studio server'));
209
- }
210
- return (0, call_add_keyframe_1.callAddSequenceKeyframe)({
211
- fileName: validatedLocation.source,
212
- nodePath,
213
- fieldKey: field.key,
214
- sourceFrame,
215
- value,
216
- schema,
217
- setPropStatuses,
218
- clientId,
219
- });
220
- }, [
221
- clientId,
222
- field.key,
223
- nodePath,
224
- schema,
225
- setPropStatuses,
226
- validatedLocation.source,
227
- ]);
228
- const onKeyframedDragValueChange = (0, react_1.useCallback)((value) => {
229
- if (propStatus === null || !isKeyframedStatus(propStatus)) {
230
- throw new Error('Expected keyframed status');
231
- }
232
- setDragOverrides(nodePath, field.key, remotion_1.Internals.makeKeyframedDragOverride({
233
- status: propStatus,
234
- frame: jsxFrame,
235
- value,
236
- }));
237
- }, [propStatus, field.key, jsxFrame, nodePath, setDragOverrides]);
238
- const onKeyframedDragEnd = (0, react_1.useCallback)(() => {
239
- clearDragOverrides(nodePath);
240
- }, [clearDragOverrides, nodePath]);
241
245
  const onOpenKeyframeSettings = (0, react_1.useCallback)(() => {
242
246
  var _a;
243
247
  if (propStatus === null || !isKeyframedStatus(propStatus)) {
@@ -302,8 +306,8 @@ const TimelineSequencePropItem = ({ field, validatedLocation, rowDepth, nodePath
302
306
  if (propStatus === null) {
303
307
  return null;
304
308
  }
305
- const row = (jsx_runtime_1.jsxs(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, showSelectedBackground: true, containsSelection: false, outerHeight: null, children: [
306
- jsx_runtime_1.jsx(TimelineFieldLabel_1.TimelineFieldLabel, { rowDepth: rowDepth, selected: selection.selected, label: (_b = field.description) !== null && _b !== void 0 ? _b : field.key }), isKeyframedStatus(propStatus) ? (jsx_runtime_1.jsx("div", { style: timeline_field_row_layout_1.timelineFieldValueColumnStyle, children: jsx_runtime_1.jsx(TimelineKeyframedValue_1.TimelineKeyframedValue, { field: field, propStatus: propStatus, keyframeDisplayOffset: keyframeDisplayOffset, dragOverrideValue: dragOverrideValue, onSave: onSaveKeyframed, onDragValueChange: onKeyframedDragValueChange, onDragEnd: onKeyframedDragEnd, scaleLockNodePath: nodePath }) })) : propStatus.status === 'static' ? (jsx_runtime_1.jsx("div", { style: timeline_field_row_layout_1.timelineFieldValueColumnStyle, children: jsx_runtime_1.jsx(Value, { field: field, nodePath: nodePath, validatedLocation: validatedLocation, schema: schema, propStatus: propStatus }) })) : (jsx_runtime_1.jsx("div", { style: timeline_field_row_layout_1.timelineFieldValueColumnStyle, children: jsx_runtime_1.jsx(TimelineSchemaField_1.TimelineNonEditableStatus, { propStatus: propStatus }) }))] }));
309
+ const row = (jsx_runtime_1.jsxs(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, showSelectedBackground: true, containsSelection: false, outerHeight: null, children: [
310
+ jsx_runtime_1.jsx(TimelineFieldLabel_1.TimelineFieldLabel, { rowDepth: rowDepth, selected: selection.selected, label: (_b = field.description) !== null && _b !== void 0 ? _b : field.key }), isKeyframedStatus(propStatus) ? (jsx_runtime_1.jsx("div", { style: timeline_field_row_layout_1.timelineFieldValueColumnStyle, children: jsx_runtime_1.jsx(exports.TimelineSequenceKeyframedValue, { field: field, fileName: validatedLocation.source, nodePath: nodePath, schema: schema, propStatus: propStatus, sourceFrame: sourceFrame }) })) : propStatus.status === 'static' ? (jsx_runtime_1.jsx("div", { style: timeline_field_row_layout_1.timelineFieldValueColumnStyle, children: jsx_runtime_1.jsx(Value, { field: field, nodePath: nodePath, validatedLocation: validatedLocation, schema: schema, propStatus: propStatus }) })) : (jsx_runtime_1.jsx("div", { style: timeline_field_row_layout_1.timelineFieldValueColumnStyle, children: jsx_runtime_1.jsx(TimelineSchemaField_1.TimelineNonEditableStatus, { propStatus: propStatus }) }))] }));
307
311
  return (jsx_runtime_1.jsx(ContextMenu_1.ContextMenu, { values: contextMenuValues, onOpen: selection.selectable ? selection.onSelect : null, children: row }));
308
312
  };
309
313
  exports.TimelineSequencePropItem = TimelineSequencePropItem;
@@ -92,12 +92,12 @@ const getTimelineSequenceFromDragChanges = ({ targets, deltaFrames, }) => {
92
92
  };
93
93
  exports.getTimelineSequenceFromDragChanges = getTimelineSequenceFromDragChanges;
94
94
  const findSequenceTrack = ({ tracks, nodePathInfo, }) => {
95
- const key = (0, studio_shared_1.stringifySequenceSubscriptionKey)(nodePathInfo.sequenceSubscriptionKey);
95
+ const key = (0, studio_shared_1.stringifySequenceExpandedRowKey)(nodePathInfo.sequenceSubscriptionKey);
96
96
  return tracks.find((candidate) => {
97
97
  if (candidate.nodePathInfo === null) {
98
98
  return false;
99
99
  }
100
- return ((0, studio_shared_1.stringifySequenceSubscriptionKey)(candidate.nodePathInfo.sequenceSubscriptionKey) === key && candidate.nodePathInfo.index === nodePathInfo.index);
100
+ return ((0, studio_shared_1.stringifySequenceExpandedRowKey)(candidate.nodePathInfo.sequenceSubscriptionKey) === key && candidate.nodePathInfo.index === nodePathInfo.index);
101
101
  });
102
102
  };
103
103
  const getTimelineSequenceDurationDragTargets = ({ draggedNodePathInfo, selectedItems, sequences, overrideIdsToNodePaths, propStatuses, }) => {
@@ -120,11 +120,12 @@ const getTimelineSequenceDurationDragTargets = ({ draggedNodePathInfo, selectedI
120
120
  ? sequences.find((sequence) => sequence.id === track.sequence.id)
121
121
  : null;
122
122
  if (!track ||
123
+ !track.nodePathInfo ||
123
124
  !originalSequence ||
124
125
  !isDurationDraggableSequence(originalSequence)) {
125
126
  return null;
126
127
  }
127
- const nodePath = nodePathInfo.sequenceSubscriptionKey;
128
+ const nodePath = track.nodePathInfo.sequenceSubscriptionKey;
128
129
  if (!canUpdateDurationInFrames({ propStatuses, nodePath })) {
129
130
  return null;
130
131
  }
@@ -160,11 +161,12 @@ const getTimelineSequenceFromDragTargets = ({ draggedNodePathInfo, selectedItems
160
161
  ? sequences.find((sequence) => sequence.id === track.sequence.id)
161
162
  : null;
162
163
  if (!track ||
164
+ !track.nodePathInfo ||
163
165
  !originalSequence ||
164
166
  !isFromDraggableSequence(originalSequence)) {
165
167
  return null;
166
168
  }
167
- const nodePath = nodePathInfo.sequenceSubscriptionKey;
169
+ const nodePath = track.nodePathInfo.sequenceSubscriptionKey;
168
170
  if (!canUpdateFrom({ propStatuses, nodePath })) {
169
171
  return null;
170
172
  }
@@ -4,6 +4,7 @@ exports.TimelineTransformOriginField = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const InputDragger_1 = require("../NewComposition/InputDragger");
7
+ const timeline_field_display_utils_1 = require("./timeline-field-display-utils");
7
8
  const timeline_field_utils_1 = require("./timeline-field-utils");
8
9
  const TimelineSchemaField_1 = require("./TimelineSchemaField");
9
10
  const transform_origin_utils_1 = require("./transform-origin-utils");
@@ -31,13 +32,11 @@ const TimelineTransformOriginField = ({ field, propStatus, effectiveValue, onSav
31
32
  step: configuredStep,
32
33
  }), [configuredStep]);
33
34
  const formatter = (0, react_1.useCallback)((v) => {
34
- const formatted = (0, timeline_field_utils_1.formatTimelineNumber)({
35
- decimalPlaces,
36
- fixed: false,
35
+ return (0, timeline_field_display_utils_1.formatTimelineFieldValueForDisplay)({
36
+ fieldSchema: field.fieldSchema,
37
37
  value: v,
38
38
  });
39
- return `${formatted}%`;
40
- }, [decimalPlaces]);
39
+ }, [field.fieldSchema]);
41
40
  const serialize = (0, react_1.useCallback)((x, y) => {
42
41
  var _a;
43
42
  return (0, transform_origin_utils_1.serializeTransformOrigin)({
@@ -4,6 +4,7 @@ exports.TimelineTranslateField = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const InputDragger_1 = require("../NewComposition/InputDragger");
7
+ const timeline_field_display_utils_1 = require("./timeline-field-display-utils");
7
8
  const timeline_field_utils_1 = require("./timeline-field-utils");
8
9
  const timeline_translate_utils_1 = require("./timeline-translate-utils");
9
10
  const leftDraggerStyle = {
@@ -27,13 +28,11 @@ const TimelineTranslateField = ({ field, propStatus, effectiveValue, onSave, onD
27
28
  step: configuredStep,
28
29
  }), [configuredStep]);
29
30
  const formatter = (0, react_1.useCallback)((v) => {
30
- const formatted = (0, timeline_field_utils_1.formatTimelineNumber)({
31
- decimalPlaces,
32
- fixed: false,
31
+ return (0, timeline_field_display_utils_1.formatTimelineFieldValueForDisplay)({
32
+ fieldSchema: field.fieldSchema,
33
33
  value: v,
34
34
  });
35
- return `${formatted}px`;
36
- }, [decimalPlaces]);
35
+ }, [field.fieldSchema]);
37
36
  // --- X callbacks ---
38
37
  const onXChange = (0, react_1.useCallback)((newVal) => {
39
38
  setDragX(newVal);
@@ -4,6 +4,7 @@ exports.TimelineUvCoordinateField = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const InputDragger_1 = require("../NewComposition/InputDragger");
7
+ const timeline_field_display_utils_1 = require("./timeline-field-display-utils");
7
8
  const timeline_field_utils_1 = require("./timeline-field-utils");
8
9
  const leftDraggerStyle = {
9
10
  paddingLeft: 0,
@@ -49,12 +50,11 @@ const TimelineUvCoordinateField = ({ field, propStatus, effectiveValue, onSave,
49
50
  step: configuredStep,
50
51
  }), [configuredStep]);
51
52
  const formatter = (0, react_1.useCallback)((v) => {
52
- return (0, timeline_field_utils_1.formatTimelineNumber)({
53
- decimalPlaces,
54
- fixed: true,
53
+ return (0, timeline_field_display_utils_1.formatTimelineFieldValueForDisplay)({
54
+ fieldSchema: field.fieldSchema,
55
55
  value: v,
56
56
  });
57
- }, [decimalPlaces]);
57
+ }, [field.fieldSchema]);
58
58
  const onXChange = (0, react_1.useCallback)((newVal) => {
59
59
  setDragX(newVal);
60
60
  const currentY = dragY !== null && dragY !== void 0 ? dragY : codeY;
@@ -1,4 +1,4 @@
1
- import type { SequencePropsSubscriptionKey, SequenceSchema } from 'remotion';
1
+ import type { SequencePropsSubscriptionKey, InteractivitySchema } from 'remotion';
2
2
  import type { SetPropStatuses } from './save-sequence-prop';
3
3
  export type AddSequenceKeyframeChange = {
4
4
  fileName: string;
@@ -6,7 +6,7 @@ export type AddSequenceKeyframeChange = {
6
6
  fieldKey: string;
7
7
  sourceFrame: number;
8
8
  value: unknown;
9
- schema: SequenceSchema;
9
+ schema: InteractivitySchema;
10
10
  };
11
11
  export type AddEffectKeyframeChange = AddSequenceKeyframeChange & {
12
12
  effectIndex: number;
@@ -17,7 +17,7 @@ export declare const callAddSequenceKeyframe: ({ fileName, nodePath, fieldKey, s
17
17
  fieldKey: string;
18
18
  sourceFrame: number;
19
19
  value: unknown;
20
- schema: SequenceSchema;
20
+ schema: InteractivitySchema;
21
21
  setPropStatuses: SetPropStatuses;
22
22
  clientId: string;
23
23
  }) => Promise<void>;
@@ -34,7 +34,7 @@ export declare const callAddEffectKeyframe: ({ fileName, nodePath, effectIndex,
34
34
  fieldKey: string;
35
35
  sourceFrame: number;
36
36
  value: unknown;
37
- schema: SequenceSchema;
37
+ schema: InteractivitySchema;
38
38
  setPropStatuses: SetPropStatuses;
39
39
  clientId: string;
40
40
  }) => Promise<void>;