@remotion/studio 4.0.527 → 4.0.528

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 (258) hide show
  1. package/dist/components/AgentPrompt.js +1 -2
  2. package/dist/components/AudioWaveform.d.ts +1 -0
  3. package/dist/components/AudioWaveform.js +10 -14
  4. package/dist/components/CodeFrame.js +1 -1
  5. package/dist/components/ColorPicker/checker.d.ts +1 -1
  6. package/dist/components/CurrentAsset.js +3 -2
  7. package/dist/components/EditorRuler/Ruler.js +6 -3
  8. package/dist/components/EffectPickerModal.js +69 -43
  9. package/dist/components/ElementInstallConfirmation.js +3 -3
  10. package/dist/components/ElementLibrariesSettings.d.ts +2 -0
  11. package/dist/components/ElementLibrariesSettings.js +200 -0
  12. package/dist/components/InitialCompositionLoader.js +3 -1
  13. package/dist/components/InspectorOpenInEditor.js +13 -0
  14. package/dist/components/InspectorPanel/AlignmentControls.js +28 -9
  15. package/dist/components/InspectorPanel/CollapsibleInspectorSectionHeader.js +1 -1
  16. package/dist/components/InspectorPanel/EasingInspector.js +6 -2
  17. package/dist/components/InspectorPanel/ElementLibraryButton.js +1 -1
  18. package/dist/components/InspectorPanel/KeyframeEasingNavigator.js +1 -1
  19. package/dist/components/InspectorPanel/KeyframeInspector.js +28 -24
  20. package/dist/components/InspectorPanel/MultiSequenceNumberField.js +1 -1
  21. package/dist/components/InspectorPanel/SequenceInspectorHeader.d.ts +3 -1
  22. package/dist/components/InspectorPanel/SequenceSelectionInspector.js +30 -2
  23. package/dist/components/InspectorPanel/SequenceWrapAction.d.ts +8 -0
  24. package/dist/components/InspectorPanel/SequenceWrapAction.js +151 -0
  25. package/dist/components/InspectorPanel/easing-inspector-selection.d.ts +2 -1
  26. package/dist/components/InspectorPanel/easing-inspector-selection.js +4 -3
  27. package/dist/components/InspectorPanel/keyframe-inspector-frame.d.ts +2 -1
  28. package/dist/components/InspectorPanel/keyframe-inspector-frame.js +2 -2
  29. package/dist/components/InspectorSequenceSection.d.ts +1 -0
  30. package/dist/components/InspectorSequenceSection.js +7 -5
  31. package/dist/components/KeyboardShortcutsSettings.js +1 -1
  32. package/dist/components/Menu/styles.d.ts +2 -2
  33. package/dist/components/Modals.js +7 -6
  34. package/dist/components/ModelManager.js +10 -9
  35. package/dist/components/NewComposition/CancelButton.js +10 -4
  36. package/dist/components/NewComposition/InputDragger.d.ts +3 -1
  37. package/dist/components/NewComposition/InputDragger.js +28 -9
  38. package/dist/components/NewComposition/NewComposition.js +7 -6
  39. package/dist/components/NewComposition/RemInput.d.ts +1 -1
  40. package/dist/components/NewComposition/menu-typeahead.js +1 -1
  41. package/dist/components/Preview.js +3 -2
  42. package/dist/components/RenderModal/SchemaEditor/create-zod-values.js +1 -2
  43. package/dist/components/RenderModal/WebRenderModalPicture.js +1 -2
  44. package/dist/components/RenderQueue/CaptionQueueItem.js +14 -5
  45. package/dist/components/RenderQueue/CaptionQueueProcessor.js +30 -7
  46. package/dist/components/RenderQueue/QueueJobError.d.ts +8 -0
  47. package/dist/components/RenderQueue/QueueJobError.js +24 -0
  48. package/dist/components/RenderQueue/QueueJobErrorModal.d.ts +8 -0
  49. package/dist/components/RenderQueue/QueueJobErrorModal.js +63 -0
  50. package/dist/components/RenderQueue/RenderQueueItemCancelButton.d.ts +3 -1
  51. package/dist/components/RenderQueue/RenderQueueItemCancelButton.js +11 -4
  52. package/dist/components/RenderQueue/RenderQueueRepeat.d.ts +3 -1
  53. package/dist/components/RenderQueue/RenderQueueRepeat.js +20 -3
  54. package/dist/components/RenderQueue/VideoMattingQueueItem.js +24 -27
  55. package/dist/components/RenderQueue/VideoMattingQueueProcessor.js +68 -28
  56. package/dist/components/RenderQueue/caption-job-types.d.ts +3 -1
  57. package/dist/components/RenderQueue/context.d.ts +4 -0
  58. package/dist/components/RenderQueue/context.js +58 -8
  59. package/dist/components/RenderQueue/index.js +2 -3
  60. package/dist/components/RenderQueue/load-model-for-job.d.ts +2 -1
  61. package/dist/components/RenderQueue/load-model-for-job.js +5 -1
  62. package/dist/components/RenderQueue/video-matting-job-types.d.ts +13 -6
  63. package/dist/components/SelectedOutlineCropControls.js +2 -1
  64. package/dist/components/SelectedOutlineEditingHandles.js +9 -2
  65. package/dist/components/SelectedOutlineElement.js +9 -3
  66. package/dist/components/SelectedOutlineKeyboardControls.d.ts +2 -4
  67. package/dist/components/SelectedOutlineKeyboardControls.js +4 -22
  68. package/dist/components/SelectedOutlineOverlay.js +152 -106
  69. package/dist/components/SelectedOutlinePathPoints.d.ts +8 -0
  70. package/dist/components/SelectedOutlinePathPoints.js +433 -0
  71. package/dist/components/SelectedOutlinePolygon.js +21 -46
  72. package/dist/components/SelectedOutlineRenderer.d.ts +3 -5
  73. package/dist/components/SelectedOutlineRenderer.js +32 -136
  74. package/dist/components/SelectedOutlineTransformOriginHandle.js +3 -2
  75. package/dist/components/SelectedOutlineUvControls.js +12 -7
  76. package/dist/components/SettingsModal.js +30 -3
  77. package/dist/components/SettingsModalFooter.d.ts +1 -0
  78. package/dist/components/SettingsModalFooter.js +7 -3
  79. package/dist/components/ShowOutlinesProvider.js +1 -1
  80. package/dist/components/SkillsSettings.d.ts +0 -1
  81. package/dist/components/SkillsSettings.js +13 -14
  82. package/dist/components/Splitter/SplitterElement.js +1 -2
  83. package/dist/components/TimeValue.js +1 -1
  84. package/dist/components/Timeline/LoopedTimelineIndicators.d.ts +1 -0
  85. package/dist/components/Timeline/LoopedTimelineIndicators.js +7 -6
  86. package/dist/components/Timeline/TimelineArrayField.js +1 -1
  87. package/dist/components/Timeline/TimelineClipboardKeybindings.js +0 -1
  88. package/dist/components/Timeline/TimelineColorField.js +1 -1
  89. package/dist/components/Timeline/TimelineDragHandler.js +1 -1
  90. package/dist/components/Timeline/TimelineEffectPropItem.d.ts +1 -0
  91. package/dist/components/Timeline/TimelineEffectPropItem.js +12 -5
  92. package/dist/components/Timeline/TimelineExpandedRow.d.ts +1 -0
  93. package/dist/components/Timeline/TimelineExpandedRow.js +5 -4
  94. package/dist/components/Timeline/TimelineExpandedSection.d.ts +1 -0
  95. package/dist/components/Timeline/TimelineExpandedSection.js +2 -2
  96. package/dist/components/Timeline/TimelineExpandedTrackKeyframes.d.ts +1 -0
  97. package/dist/components/Timeline/TimelineExpandedTrackKeyframes.js +3 -1
  98. package/dist/components/Timeline/TimelineFontFamilyField.js +12 -12
  99. package/dist/components/Timeline/TimelineKeyframeControls.d.ts +1 -0
  100. package/dist/components/Timeline/TimelineKeyframeControls.js +39 -28
  101. package/dist/components/Timeline/TimelineLayerChildren.js +1 -1
  102. package/dist/components/Timeline/TimelineList.js +1 -1
  103. package/dist/components/Timeline/TimelineNumberField.js +2 -4
  104. package/dist/components/Timeline/TimelinePrimitiveFieldValue.js +1 -1
  105. package/dist/components/Timeline/TimelineSelection.d.ts +9 -9
  106. package/dist/components/Timeline/TimelineSelection.js +16 -9
  107. package/dist/components/Timeline/TimelineSequence.d.ts +3 -1
  108. package/dist/components/Timeline/TimelineSequence.js +39 -21
  109. package/dist/components/Timeline/TimelineSequenceItem.d.ts +1 -0
  110. package/dist/components/Timeline/TimelineSequenceItem.js +18 -8
  111. package/dist/components/Timeline/TimelineSequencePropItem.d.ts +3 -0
  112. package/dist/components/Timeline/TimelineSequencePropItem.js +262 -25
  113. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.d.ts +11 -13
  114. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +98 -77
  115. package/dist/components/Timeline/TimelineTextContentField.js +27 -4
  116. package/dist/components/Timeline/TimelineTimeIndicators.js +10 -5
  117. package/dist/components/Timeline/TimelineTrack.js +1 -1
  118. package/dist/components/Timeline/TimelineTrimTooltip.d.ts +11 -0
  119. package/dist/components/Timeline/TimelineTrimTooltip.js +41 -0
  120. package/dist/components/Timeline/TimelineVideoInfo.d.ts +1 -0
  121. package/dist/components/Timeline/TimelineVideoInfo.js +13 -10
  122. package/dist/components/Timeline/delete-selected-keyframe.js +22 -8
  123. package/dist/components/Timeline/delete-selected-timeline-item.d.ts +1 -5
  124. package/dist/components/Timeline/delete-selected-timeline-item.js +7 -93
  125. package/dist/components/Timeline/get-animation-item-selection-for-frame.d.ts +2 -1
  126. package/dist/components/Timeline/get-animation-item-selection-for-frame.js +7 -5
  127. package/dist/components/Timeline/get-keyframed-sequence-drag-targets.d.ts +23 -0
  128. package/dist/components/Timeline/get-keyframed-sequence-drag-targets.js +57 -0
  129. package/dist/components/Timeline/get-node-keyframes.d.ts +2 -1
  130. package/dist/components/Timeline/get-node-keyframes.js +6 -4
  131. package/dist/components/Timeline/get-playback-rate-keyframe-changes.d.ts +21 -0
  132. package/dist/components/Timeline/get-playback-rate-keyframe-changes.js +142 -0
  133. package/dist/components/Timeline/get-timeline-keyframes.d.ts +15 -2
  134. package/dist/components/Timeline/get-timeline-keyframes.js +44 -6
  135. package/dist/components/Timeline/keyframe-clipboard.js +17 -3
  136. package/dist/components/Timeline/split-selected-timeline-item.js +4 -1
  137. package/dist/components/Timeline/timeline-field-display-utils.js +1 -0
  138. package/dist/components/Timeline/timeline-field-row-layout.js +1 -0
  139. package/dist/components/Timeline/use-delete-timeline-items.js +17 -11
  140. package/dist/components/Timeline/use-expanded-track-keyframe-rows.d.ts +2 -1
  141. package/dist/components/Timeline/use-expanded-track-keyframe-rows.js +3 -1
  142. package/dist/components/Timeline/use-sequence-freeze-frame-menu-item.js +7 -3
  143. package/dist/components/Timeline/use-timeline-keyframe-drag.js +28 -19
  144. package/dist/components/Transcription/Models.js +1 -1
  145. package/dist/components/Transcription/TranscriptionModal.js +3 -1
  146. package/dist/components/Transcription/resample-media-to-16-khz.d.ts +2 -1
  147. package/dist/components/Transcription/resample-media-to-16-khz.js +20 -2
  148. package/dist/components/UpdatesSettings.js +2 -0
  149. package/dist/components/VideoMatting/Models.js +1 -1
  150. package/dist/components/VideoMatting/VideoMattingModal.js +30 -47
  151. package/dist/components/VideoMatting/VideoMattingModalWithOptionalPackage.js +1 -1
  152. package/dist/components/WebMcp.js +22 -40
  153. package/dist/components/composition-drop-preview.js +1 -0
  154. package/dist/components/effect-drag-and-drop.d.ts +13 -5
  155. package/dist/components/effect-drag-and-drop.js +19 -4
  156. package/dist/components/get-open-in-menu-items.d.ts +2 -1
  157. package/dist/components/get-open-in-menu-items.js +17 -1
  158. package/dist/components/selected-outline-drag.d.ts +1 -6
  159. package/dist/components/selected-outline-drag.js +22 -6
  160. package/dist/components/selected-outline-geometry.d.ts +2 -18
  161. package/dist/components/selected-outline-measurement.d.ts +23 -41
  162. package/dist/components/selected-outline-measurement.js +14 -252
  163. package/dist/components/selected-outline-order.d.ts +4 -11
  164. package/dist/components/selected-outline-order.js +2 -254
  165. package/dist/components/selected-outline-snap.d.ts +1 -1
  166. package/dist/components/selected-outline-snap.js +2 -1
  167. package/dist/components/selected-outline-types.d.ts +18 -28
  168. package/dist/components/selected-outline-uv.d.ts +4 -4
  169. package/dist/components/selected-outline-uv.js +6 -111
  170. package/dist/components/sequence-props-api.js +0 -10
  171. package/dist/components/use-selected-outline-control-target.js +12 -21
  172. package/dist/components/wrap-jsx-node-api.d.ts +2 -0
  173. package/dist/components/wrap-jsx-node-api.js +13 -0
  174. package/dist/error-overlay/remotion-overlay/OpenInEditor.js +45 -2
  175. package/dist/error-overlay/remotion-overlay/StackFrame.js +32 -3
  176. package/dist/esm/{CaptionQueueProcessor-npa6szn1.mjs → CaptionQueueProcessor-nr7hjcga.mjs} +63 -17
  177. package/dist/esm/LazyModels-ajkn7fs3.mjs +12 -0
  178. package/dist/esm/LazyModels-g1g7cf4e.mjs +12 -0
  179. package/dist/esm/{TranscriptionModal-79m5wgcj.mjs → TranscriptionModal-e18bzbkb.mjs} +15 -15
  180. package/dist/esm/{VideoMattingModal-31pew0xj.mjs → VideoMattingModal-5bz2s4rs.mjs} +47 -65
  181. package/dist/esm/{VideoMattingQueueProcessor-t1hgm2rm.mjs → VideoMattingQueueProcessor-4tkj0f4k.mjs} +69 -26
  182. package/dist/esm/{index-v4tr1bft.mjs → index-09txs1bj.mjs} +5 -0
  183. package/dist/esm/{index-n5gmcvhz.mjs → index-5ycb9e9q.mjs} +2 -4
  184. package/dist/esm/{index-5t2dwxsk.mjs → index-890dd9b3.mjs} +259 -21
  185. package/dist/esm/{index-ac5550e7.mjs → index-8nt6a0mw.mjs} +3 -3
  186. package/dist/esm/{index-614tdz2q.mjs → index-9q9w8v9p.mjs} +3 -3
  187. package/dist/esm/{index-s7qa3xbw.mjs → index-c2wabcdt.mjs} +6 -6
  188. package/dist/esm/{index-r1gr3j3a.mjs → index-dfy1t576.mjs} +50 -1
  189. package/dist/esm/{index-21hxsfaa.mjs → index-dh3zk2hv.mjs} +6 -25
  190. package/dist/esm/{index-4zen9prq.mjs → index-dpyss74p.mjs} +6563 -5485
  191. package/dist/esm/{index-9x6e1dq0.mjs → index-hqxc6tzp.mjs} +40 -6
  192. package/dist/esm/{index-9xxg6218.mjs → index-qve7mdfp.mjs} +19 -1
  193. package/dist/esm/{index-e855w59j.mjs → index-s6qya2gg.mjs} +3 -5
  194. package/dist/esm/index-t7tbt980.mjs +103 -0
  195. package/dist/esm/{index-r0ejh5sy.mjs → index-t7xnxdf8.mjs} +44 -26
  196. package/dist/esm/index-wqc43mw0.mjs +158 -0
  197. package/dist/esm/{index-ppspzgn9.mjs → index-x6r9bn12.mjs} +4026 -4761
  198. package/dist/esm/{index-vxwg66ar.mjs → index-xac20sv4.mjs} +44 -57
  199. package/dist/esm/index.mjs +4 -5
  200. package/dist/esm/internals.mjs +13 -13
  201. package/dist/esm/previewEntry.mjs +18 -15
  202. package/dist/esm/renderEntry.mjs +5 -1
  203. package/dist/helpers/calculate-timeline.d.ts +5 -1
  204. package/dist/helpers/calculate-timeline.js +1 -1
  205. package/dist/helpers/checkerboard-background.d.ts +2 -2
  206. package/dist/helpers/colors.d.ts +132 -112
  207. package/dist/helpers/colors.js +117 -95
  208. package/dist/helpers/create-folder-tree.js +2 -1
  209. package/dist/helpers/editor-guide-selection.d.ts +1 -1
  210. package/dist/helpers/editor-ruler.js +23 -12
  211. package/dist/helpers/get-connected-compositions.d.ts +6 -1
  212. package/dist/helpers/get-connected-compositions.js +1 -1
  213. package/dist/helpers/get-sequence-double-click-action.js +1 -1
  214. package/dist/helpers/get-sequence-visible-range.d.ts +1 -1
  215. package/dist/helpers/get-sequence-visible-range.js +2 -5
  216. package/dist/helpers/get-timeline-nestedness.d.ts +1 -1
  217. package/dist/helpers/get-timeline-nestedness.js +1 -1
  218. package/dist/helpers/get-timeline-sequence-sort-key.d.ts +1 -1
  219. package/dist/helpers/get-timeline-sequence-sort-key.js +1 -1
  220. package/dist/helpers/hoverable.js +4 -4
  221. package/dist/helpers/inject-css.js +5 -7
  222. package/dist/helpers/prism-vsc-dark-plus.d.ts +1 -1
  223. package/dist/helpers/prism-vsc-dark-plus.js +52 -51
  224. package/dist/helpers/resolve-studio-color.d.ts +1 -0
  225. package/dist/helpers/resolve-studio-color.js +11 -0
  226. package/dist/helpers/studio-css-variables.d.ts +1 -0
  227. package/dist/helpers/studio-css-variables.js +105 -0
  228. package/dist/helpers/studio-pixel-ratio.d.ts +1 -0
  229. package/dist/helpers/studio-pixel-ratio.js +7 -0
  230. package/dist/helpers/timeline-node-path-key.d.ts +1 -1
  231. package/dist/helpers/timeline-node-path-key.js +2 -2
  232. package/dist/helpers/use-runtime-values.js +2 -28
  233. package/dist/hot-middleware-client/client.js +5 -3
  234. package/dist/icons/align-center-horizontal.js +2 -1
  235. package/dist/icons/align-left.js +2 -1
  236. package/dist/icons/align-right.js +2 -1
  237. package/dist/icons/{separation.d.ts → background-removal.d.ts} +1 -1
  238. package/dist/icons/background-removal.js +9 -0
  239. package/dist/icons/wrap.d.ts +4 -0
  240. package/dist/icons/wrap.js +10 -0
  241. package/dist/previewEntry.js +2 -0
  242. package/dist/renderEntry.js +2 -0
  243. package/dist/state/modals.d.ts +15 -1
  244. package/dist/state/timeline-sequence-hover.d.ts +6 -16
  245. package/dist/state/timeline-sequence-hover.js +6 -67
  246. package/package.json +20 -19
  247. package/dist/components/Timeline/get-easing-selection-after-keyframe-delete.d.ts +0 -15
  248. package/dist/components/Timeline/get-easing-selection-after-keyframe-delete.js +0 -31
  249. package/dist/esm/LazyModels-nh3c8h9p.mjs +0 -12
  250. package/dist/esm/LazyModels-rr5v8h5y.mjs +0 -12
  251. package/dist/esm/index-cw0pnpg5.mjs +0 -50
  252. package/dist/esm/index-k426ye99.mjs +0 -139
  253. package/dist/helpers/get-box-quads-polyfill-internals.d.ts +0 -82
  254. package/dist/helpers/get-box-quads-polyfill-internals.js +0 -2403
  255. package/dist/helpers/get-box-quads-ponyfill.d.ts +0 -10
  256. package/dist/helpers/get-box-quads-ponyfill.js +0 -23
  257. package/dist/icons/separation.js +0 -7
  258. /package/dist/esm/{resolve-composition-component-location-qrp05g62.mjs → resolve-composition-component-location-2hgf6g0a.mjs} +0 -0
@@ -6,6 +6,7 @@ const react_1 = require("react");
6
6
  const browser_studio_operations_1 = require("../helpers/browser-studio-operations");
7
7
  const client_id_1 = require("../helpers/client-id");
8
8
  const colors_1 = require("../helpers/colors");
9
+ const copy_text_1 = require("../helpers/copy-text");
9
10
  const get_git_menu_item_1 = require("../helpers/get-git-menu-item");
10
11
  const open_in_editor_1 = require("../helpers/open-in-editor");
11
12
  const caret_1 = require("../icons/caret");
@@ -57,6 +58,16 @@ const InspectorOpenInEditor = ({ contextForAgents = null, label, location, locat
57
58
  (0, NotificationCenter_1.showNotification)(err.message, 2000);
58
59
  }
59
60
  }, [contextForAgents]);
61
+ const copyPath = (0, react_1.useCallback)(() => {
62
+ if (!(location === null || location === void 0 ? void 0 : location.source)) {
63
+ return;
64
+ }
65
+ (0, copy_text_1.copyText)(location.source)
66
+ .then(() => (0, NotificationCenter_1.showNotification)('Copied path', 1500))
67
+ .catch((err) => {
68
+ (0, NotificationCenter_1.showNotification)(`Could not copy path: ${err.message}`, 2000);
69
+ });
70
+ }, [location]);
60
71
  const defaultAppName = defaultOpenInTarget === 'git-source'
61
72
  ? 'GitHub'
62
73
  : (defaultEditorName !== null && defaultEditorName !== void 0 ? defaultEditorName : 'default editor');
@@ -89,6 +100,7 @@ const InspectorOpenInEditor = ({ contextForAgents = null, label, location, locat
89
100
  folder: locationType === 'folder',
90
101
  gitSourceDisabled: location === null,
91
102
  onConfigureApps: configureDefaultApps,
103
+ onCopyPath: locationType === 'folder' && (location === null || location === void 0 ? void 0 : location.source) ? copyPath : undefined,
92
104
  onOpenInCodingAgent: (codingAgentId, codingAgentName) => {
93
105
  openWithCodingAgent(codingAgentId, codingAgentName).catch(() => undefined);
94
106
  },
@@ -138,6 +150,7 @@ const InspectorOpenInEditor = ({ contextForAgents = null, label, location, locat
138
150
  canConfigureApps,
139
151
  canOpenInEditor,
140
152
  configureDefaultApps,
153
+ copyPath,
141
154
  defaultEditorId,
142
155
  defaultOpenInTarget,
143
156
  editorInfo,
@@ -78,11 +78,16 @@ const AlignmentControls = ({ track }) => {
78
78
  const nodePath = track.nodePathInfo.sequenceSubscriptionKey;
79
79
  const nodePropStatuses = remotion_1.Internals.getPropStatusesCtx(propStatuses, nodePath);
80
80
  const firstKeyframedStatus = Object.values(nodePropStatuses !== null && nodePropStatuses !== void 0 ? nodePropStatuses : {}).find((status) => status.status === 'keyframed');
81
- const sourceFrame = timelinePosition -
82
- (0, get_timeline_keyframes_1.getKeyframeDisplayOffset)({
83
- propStatus: firstKeyframedStatus,
81
+ const sourceFrame = (0, get_timeline_keyframes_1.getKeyframeSourceFrame)({
82
+ displayFrame: timelinePosition,
83
+ propStatus: firstKeyframedStatus !== null && firstKeyframedStatus !== void 0 ? firstKeyframedStatus : null,
84
+ keyframeDisplayOffset: (0, get_timeline_keyframes_1.getKeyframeDisplayOffset)({
85
+ propStatus: firstKeyframedStatus !== null && firstKeyframedStatus !== void 0 ? firstKeyframedStatus : null,
84
86
  keyframeDisplayOffset: track.keyframeDisplayOffset,
85
- });
87
+ keyframePlaybackRate: track.keyframePlaybackRate,
88
+ }),
89
+ keyframePlaybackRate: track.keyframePlaybackRate,
90
+ });
86
91
  const dragOverrides = (_b = getDragOverrides(nodePath)) !== null && _b !== void 0 ? _b : {};
87
92
  const activeSchema = (0, selected_outline_drag_1.getSelectedOutlineActiveSchema)({
88
93
  schema: track.sequence.controls.schema,
@@ -170,7 +175,16 @@ const AlignmentControls = ({ track }) => {
170
175
  fileName: nodePath.absolutePath,
171
176
  nodePath,
172
177
  fieldKey: selected_outline_types_1.translateFieldKey,
173
- sourceFrame,
178
+ sourceFrame: (0, get_timeline_keyframes_1.getKeyframeSourceFrame)({
179
+ displayFrame: timelinePosition,
180
+ keyframeDisplayOffset: (0, get_timeline_keyframes_1.getKeyframeDisplayOffset)({
181
+ propStatus,
182
+ keyframeDisplayOffset: track.keyframeDisplayOffset,
183
+ keyframePlaybackRate: track.keyframePlaybackRate,
184
+ }),
185
+ keyframePlaybackRate: track.keyframePlaybackRate,
186
+ propStatus,
187
+ }),
174
188
  value: newValue,
175
189
  schema: track.sequence.controls.schema,
176
190
  setPropStatuses,
@@ -197,11 +211,16 @@ const AlignmentControls = ({ track }) => {
197
211
  const renderNodePath = track.nodePathInfo.sequenceSubscriptionKey;
198
212
  const renderNodePropStatuses = remotion_1.Internals.getPropStatusesCtx(propStatuses, renderNodePath);
199
213
  const firstRenderKeyframedStatus = Object.values(renderNodePropStatuses !== null && renderNodePropStatuses !== void 0 ? renderNodePropStatuses : {}).find((status) => status.status === 'keyframed');
200
- const renderSourceFrame = timelinePosition -
201
- (0, get_timeline_keyframes_1.getKeyframeDisplayOffset)({
202
- propStatus: firstRenderKeyframedStatus,
214
+ const renderSourceFrame = (0, get_timeline_keyframes_1.getKeyframeSourceFrame)({
215
+ displayFrame: timelinePosition,
216
+ propStatus: firstRenderKeyframedStatus !== null && firstRenderKeyframedStatus !== void 0 ? firstRenderKeyframedStatus : null,
217
+ keyframeDisplayOffset: (0, get_timeline_keyframes_1.getKeyframeDisplayOffset)({
218
+ propStatus: firstRenderKeyframedStatus !== null && firstRenderKeyframedStatus !== void 0 ? firstRenderKeyframedStatus : null,
203
219
  keyframeDisplayOffset: track.keyframeDisplayOffset,
204
- });
220
+ keyframePlaybackRate: track.keyframePlaybackRate,
221
+ }),
222
+ keyframePlaybackRate: track.keyframePlaybackRate,
223
+ });
205
224
  const renderDragOverrides = (_a = getDragOverrides(renderNodePath)) !== null && _a !== void 0 ? _a : {};
206
225
  const renderActiveSchema = (0, selected_outline_drag_1.getSelectedOutlineActiveSchema)({
207
226
  schema: track.sequence.controls.schema,
@@ -29,7 +29,7 @@ const staticSectionTitle = {
29
29
  const collapsibleSectionHeaderButton = {
30
30
  ...sectionTitle,
31
31
  appearance: 'none',
32
- backgroundColor: 'transparent',
32
+ backgroundColor: colors_1.TRANSPARENT,
33
33
  border: 'none',
34
34
  borderRadius: 3,
35
35
  cursor: 'default',
@@ -113,6 +113,7 @@ const EasingInspector = ({ selection }) => {
113
113
  }
114
114
  return (0, easing_inspector_selection_1.getEasingSelectionFromCurrentKeyframes)({
115
115
  keyframeDisplayOffset: track.keyframeDisplayOffset,
116
+ keyframePlaybackRate: track.keyframePlaybackRate,
116
117
  nodePathInfo: selection.nodePathInfo,
117
118
  propStatus: easingUpdate.propStatus,
118
119
  segmentIndex: easingUpdate.segmentIndex,
@@ -123,6 +124,7 @@ const EasingInspector = ({ selection }) => {
123
124
  : (0, get_timeline_keyframes_1.getKeyframeDisplayOffset)({
124
125
  propStatus: easingUpdate.propStatus,
125
126
  keyframeDisplayOffset: track.keyframeDisplayOffset,
127
+ keyframePlaybackRate: track.keyframePlaybackRate,
126
128
  });
127
129
  const state = (0, react_1.useMemo)(() => {
128
130
  if (initialEasing === null || currentEasingSelection === null) {
@@ -154,7 +156,8 @@ const EasingInspector = ({ selection }) => {
154
156
  previewServerState.type !== 'connected') {
155
157
  return;
156
158
  }
157
- const sourceFrame = timelinePosition - easingKeyframeDisplayOffset;
159
+ const sourceFrame = (timelinePosition - easingKeyframeDisplayOffset) *
160
+ track.keyframePlaybackRate;
158
161
  const value = remotion_1.Internals.getEffectiveVisualModeValue({
159
162
  propStatus: easingUpdate.propStatus,
160
163
  dragOverrideValue: easingDetails.dragOverrideValue,
@@ -208,7 +211,8 @@ const EasingInspector = ({ selection }) => {
208
211
  const renderHeader = (0, react_1.useCallback)(() => (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
209
212
  jsx_runtime_1.jsx(common_1.InspectorBackAction, { disabled: parentSelection === null, onClick: onSelectParent, title: "Back to property", children: fieldLabel }), easingUpdate === null || track === null ? null : (jsx_runtime_1.jsx(KeyframeEasingNavigator_1.KeyframeEasingNavigator, { currentSelection: currentEasingSelection !== null && currentEasingSelection !== void 0 ? currentEasingSelection : selection, includeEasings: true, keyframes: easingUpdate.propStatus.keyframes.map((keyframe) => ({
210
213
  ...keyframe,
211
- frame: keyframe.frame + easingKeyframeDisplayOffset,
214
+ frame: keyframe.frame / track.keyframePlaybackRate +
215
+ easingKeyframeDisplayOffset,
212
216
  })), nodePathInfo: selection.nodePathInfo }))] })), [
213
217
  currentEasingSelection,
214
218
  easingUpdate,
@@ -82,7 +82,7 @@ const ElementLibraryButton = () => {
82
82
  segmentId: 'element-library',
83
83
  selectedId: null,
84
84
  style: elementLibraryDropdownSegmentStyle,
85
- title: 'Choose an Element library to browse inside Studio.',
85
+ title: 'Choose an Element Library to browse inside Studio.',
86
86
  tooltipLabel: null,
87
87
  type: 'menu',
88
88
  values: [
@@ -98,7 +98,7 @@ const TimelineNavigatorItem = ({ extendLineLeft, extendLineRight, item, onSelect
98
98
  };
99
99
  const KeyframeEasingNavigator = ({ currentSelection, includeEasings, keyframes, nodePathInfo }) => {
100
100
  const { isSelected, selectItems } = (0, TimelineSelection_1.useTimelineSelection)();
101
- const setFrame = remotion_1.Internals.useTimelineSetFrame();
101
+ const setFrame = remotion_1.Internals.Timeline.useTimelineSeekFrame();
102
102
  const videoConfig = (0, remotion_1.useVideoConfig)();
103
103
  const items = (0, react_1.useMemo)(() => (0, keyframe_easing_navigator_items_1.getKeyframeEasingNavigatorItems)({
104
104
  includeEasings,
@@ -12,9 +12,7 @@ const is_menu_item_1 = require("../Menu/is-menu-item");
12
12
  const InputDragger_1 = require("../NewComposition/InputDragger");
13
13
  const call_delete_keyframe_1 = require("../Timeline/call-delete-keyframe");
14
14
  const call_move_keyframe_1 = require("../Timeline/call-move-keyframe");
15
- const get_easing_selection_after_keyframe_delete_1 = require("../Timeline/get-easing-selection-after-keyframe-delete");
16
15
  const get_timeline_keyframes_1 = require("../Timeline/get-timeline-keyframes");
17
- const imperative_state_1 = require("../Timeline/imperative-state");
18
16
  const parse_keyframe_field_from_node_path_1 = require("../Timeline/parse-keyframe-field-from-node-path");
19
17
  const TimelineEffectPropItem_1 = require("../Timeline/TimelineEffectPropItem");
20
18
  const TimelineSelection_1 = require("../Timeline/TimelineSelection");
@@ -80,7 +78,7 @@ const KeyframeInspector = ({ selection }) => {
80
78
  return null;
81
79
  }
82
80
  const nodePath = selection.nodePathInfo.sequenceSubscriptionKey;
83
- const { keyframeDisplayOffset } = track;
81
+ const { keyframeDisplayOffset, keyframePlaybackRate } = track;
84
82
  if (keyframeField.type === 'sequence') {
85
83
  const sequenceFields = (0, timeline_layout_1.getFieldsToShow)({
86
84
  schema: track.sequence.controls.schema,
@@ -100,18 +98,25 @@ const KeyframeInspector = ({ selection }) => {
100
98
  field: sequenceField,
101
99
  fieldLabel: (_d = sequenceField.description) !== null && _d !== void 0 ? _d : sequenceField.key,
102
100
  fileName: nodePath.absolutePath,
101
+ keyframePlaybackRate,
103
102
  keyframeDisplayOffset: (0, get_timeline_keyframes_1.getKeyframeDisplayOffset)({
104
103
  propStatus: sequencePropStatus,
105
104
  keyframeDisplayOffset,
105
+ keyframePlaybackRate,
106
106
  }),
107
107
  nodePath,
108
108
  propStatus: sequencePropStatus,
109
109
  schema: track.sequence.controls.schema,
110
- sourceFrame: selection.frame -
111
- (0, get_timeline_keyframes_1.getKeyframeDisplayOffset)({
110
+ sourceFrame: (0, get_timeline_keyframes_1.getKeyframeSourceFrame)({
111
+ displayFrame: selection.frame,
112
+ propStatus: sequencePropStatus,
113
+ keyframeDisplayOffset: (0, get_timeline_keyframes_1.getKeyframeDisplayOffset)({
112
114
  propStatus: sequencePropStatus,
113
115
  keyframeDisplayOffset,
116
+ keyframePlaybackRate,
114
117
  }),
118
+ keyframePlaybackRate,
119
+ }),
115
120
  };
116
121
  }
117
122
  const effect = track.sequence.effects[keyframeField.effectIndex];
@@ -143,18 +148,25 @@ const KeyframeInspector = ({ selection }) => {
143
148
  field: effectField,
144
149
  fieldLabel: (_g = effectField.description) !== null && _g !== void 0 ? _g : effectField.key,
145
150
  fileName: nodePath.absolutePath,
151
+ keyframePlaybackRate,
146
152
  keyframeDisplayOffset: (0, get_timeline_keyframes_1.getKeyframeDisplayOffset)({
147
153
  propStatus: effectPropStatus,
148
154
  keyframeDisplayOffset,
155
+ keyframePlaybackRate,
149
156
  }),
150
157
  nodePath,
151
158
  propStatus: effectPropStatus,
152
159
  schema: effect.schema,
153
- sourceFrame: selection.frame -
154
- (0, get_timeline_keyframes_1.getKeyframeDisplayOffset)({
160
+ sourceFrame: (0, get_timeline_keyframes_1.getKeyframeSourceFrame)({
161
+ displayFrame: selection.frame,
162
+ propStatus: effectPropStatus,
163
+ keyframeDisplayOffset: (0, get_timeline_keyframes_1.getKeyframeDisplayOffset)({
155
164
  propStatus: effectPropStatus,
156
165
  keyframeDisplayOffset,
166
+ keyframePlaybackRate,
157
167
  }),
168
+ keyframePlaybackRate,
169
+ }),
158
170
  validatedLocation: {
159
171
  source: nodePath.absolutePath,
160
172
  line: 1,
@@ -188,9 +200,11 @@ const KeyframeInspector = ({ selection }) => {
188
200
  if (details === null) {
189
201
  return;
190
202
  }
191
- const toFrame = (0, keyframe_inspector_frame_1.getInspectorKeyframeSourceFrame)({
203
+ const toFrame = (0, get_timeline_keyframes_1.getKeyframeSourceFrame)({
192
204
  displayFrame,
193
205
  keyframeDisplayOffset: details.keyframeDisplayOffset,
206
+ keyframePlaybackRate: details.keyframePlaybackRate,
207
+ propStatus: details.propStatus,
194
208
  });
195
209
  if (displayFrame === selection.frame || toFrame === details.sourceFrame) {
196
210
  clearFrameDragOverride(details);
@@ -227,9 +241,11 @@ const KeyframeInspector = ({ selection }) => {
227
241
  durationInFrames: videoConfig.durationInFrames,
228
242
  frame: value,
229
243
  });
230
- const toFrame = (0, keyframe_inspector_frame_1.getInspectorKeyframeSourceFrame)({
244
+ const toFrame = (0, get_timeline_keyframes_1.getKeyframeSourceFrame)({
231
245
  displayFrame,
232
246
  keyframeDisplayOffset: details.keyframeDisplayOffset,
247
+ keyframePlaybackRate: details.keyframePlaybackRate,
248
+ propStatus: details.propStatus,
233
249
  });
234
250
  setDraftFrame(displayFrame);
235
251
  clearFrameDragOverride(details);
@@ -289,19 +305,7 @@ const KeyframeInspector = ({ selection }) => {
289
305
  if (details === null || previewServerState.type !== 'connected') {
290
306
  return;
291
307
  }
292
- const easingSelection = (0, update_selected_easing_1.canEditEasingForInterpolationFunction)(details.propStatus.interpolationFunction)
293
- ? (0, get_easing_selection_after_keyframe_delete_1.getEasingSelectionAfterKeyframeDelete)({
294
- deletedSourceFrames: [details.sourceFrame],
295
- keyframeDisplayOffset: details.keyframeDisplayOffset,
296
- nodePathInfo: selection.nodePathInfo,
297
- propStatus: details.propStatus,
298
- timelinePosition: (0, imperative_state_1.getCurrentFrame)(),
299
- })
300
- : null;
301
- if (easingSelection !== null) {
302
- selectItems([easingSelection], { reveal: true });
303
- }
304
- else if (parentSelection !== null) {
308
+ if (parentSelection !== null) {
305
309
  selectItems([parentSelection], { reveal: true });
306
310
  }
307
311
  if (details.type === 'sequence') {
@@ -331,7 +335,6 @@ const KeyframeInspector = ({ selection }) => {
331
335
  parentSelection,
332
336
  previewServerState,
333
337
  selectItems,
334
- selection.nodePathInfo,
335
338
  setPropStatuses,
336
339
  ]);
337
340
  if (details === null || track === null) {
@@ -340,7 +343,8 @@ const KeyframeInspector = ({ selection }) => {
340
343
  return (jsx_runtime_1.jsxs("div", { style: styles_1.selectedContainer, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: [
341
344
  jsx_runtime_1.jsx(SequenceInspectorHeader_1.SequenceInspectorSections, { track: track }), jsx_runtime_1.jsx(common_1.InspectorBackAction, { disabled: parentSelection === null, onClick: onSelectParent, title: "Back to property", children: details.fieldLabel }), jsx_runtime_1.jsx(KeyframeEasingNavigator_1.KeyframeEasingNavigator, { currentSelection: selection, includeEasings: (0, update_selected_easing_1.canEditEasingForInterpolationFunction)(details.propStatus.interpolationFunction), keyframes: details.propStatus.keyframes.map((keyframe) => ({
342
345
  ...keyframe,
343
- frame: keyframe.frame + details.keyframeDisplayOffset,
346
+ frame: keyframe.frame / details.keyframePlaybackRate +
347
+ details.keyframeDisplayOffset,
344
348
  })), nodePathInfo: selection.nodePathInfo }), jsx_runtime_1.jsxs("div", { style: styles_1.detailsWithInlineAction, children: [
345
349
  jsx_runtime_1.jsxs("div", { style: styles_1.detailsBeforeInlineAction, children: [
346
350
  jsx_runtime_1.jsx(common_1.InspectorDetailRow, { label: "Frame", children: jsx_runtime_1.jsx(InputDragger_1.InputDragger, { type: "number", value: draftFrame, status: "ok", onValueChange: onFrameChange, onValueChangeEnd: onFrameChangeEnd, onTextChange: () => undefined, min: 0, max: Math.max(0, videoConfig.durationInFrames - 1), step: 1, formatter: (value) => String(Math.round(Number(value))), rightAlign: true, small: true }) }), jsx_runtime_1.jsx("div", { style: styles_1.keyframeEditorRow, children: jsx_runtime_1.jsx(common_1.InspectorDetailRow, { label: details.fieldLabel, children: jsx_runtime_1.jsx("div", { style: styles_1.keyframeEditorValue, children: details.type === 'sequence' ? (jsx_runtime_1.jsx(TimelineSequencePropItem_1.TimelineSequenceKeyframedValue, { field: details.field, fileName: details.fileName, nodePath: details.nodePath, schema: details.schema, propStatus: details.propStatus, sourceFrame: details.sourceFrame })) : (jsx_runtime_1.jsx(TimelineEffectPropItem_1.TimelineEffectPropValue, { field: details.field, nodePath: details.nodePath, validatedLocation: details.validatedLocation, sourceFrame: details.sourceFrame, runtimeValueStore: null })) }) }) })
@@ -63,7 +63,7 @@ const NumericAxis = ({ field, values, axis, onPreview, onSave, onClear }) => {
63
63
  }
64
64
  }, children: jsx_runtime_1.jsx(InputDragger_1.InputDragger, { type: "number", value: dragValue !== null && dragValue !== void 0 ? dragValue : coordinates[0], "aria-label": axis === null
65
65
  ? ((_d = field.description) !== null && _d !== void 0 ? _d : field.key)
66
- : `Offset ${['X', 'Y', 'Z'][axis]}`, title: "Type to set all values; drag to adjust each value", status: "ok", small: true, rightAlign: false, min: min, max: max, step: step, snapToStep: axis === null, dragDecimalPlaces: decimalPlaces, dragSensitivity: axis === null ? 1 : 3, buttonStyle: { paddingLeft: 0 }, style: { width: 70 }, formatter: (value) => mixed && dragValue === null
66
+ : `Offset ${['X', 'Y', 'Z'][axis]}`, title: "Type to set all values; drag to adjust each value", status: "ok", small: true, rightAlign: false, min: min, max: max, step: step, allowStepMismatch: true, integerOnly: schema.type === 'number' && schema.integer === true, snapToStep: axis === null, dragDecimalPlaces: decimalPlaces, dragSensitivity: axis === null ? 1 : 3, buttonStyle: { paddingLeft: 0 }, style: { width: 70 }, formatter: (value) => mixed && dragValue === null
67
67
  ? 'Mixed'
68
68
  : (0, timeline_field_display_utils_1.formatTimelineFieldValueForDisplay)({ fieldSchema: schema, value }), onTextChange: noop_1.noop, onValueChange: (value, source) => {
69
69
  var _a;
@@ -6,7 +6,9 @@ type SequenceInspectorSourceLocation = {
6
6
  readonly openFileLocation: () => void;
7
7
  readonly validatedLocation: CodePosition | null;
8
8
  };
9
- export declare const useSequenceInspectorSourceLocation: (sequence: import("remotion").TSequence) => SequenceInspectorSourceLocation;
9
+ export declare const useSequenceInspectorSourceLocation: (sequence: import("remotion").TSequence & {
10
+ loopDisplay: import("@remotion/canvas").TimelineLoopDisplay | undefined;
11
+ }) => SequenceInspectorSourceLocation;
10
12
  export declare const SequenceInspectorHeader: React.FC<{
11
13
  readonly sourceLocation: SequenceInspectorSourceLocation;
12
14
  readonly track: TimelineTrackData;
@@ -8,6 +8,7 @@ const client_id_1 = require("../../helpers/client-id");
8
8
  const interactivity_enabled_1 = require("../../helpers/interactivity-enabled");
9
9
  const use_media_metadata_1 = require("../../helpers/use-media-metadata");
10
10
  const audio_1 = require("../../icons/audio");
11
+ const background_removal_1 = require("../../icons/background-removal");
11
12
  const duplicate_1 = require("../../icons/duplicate");
12
13
  const scissors_1 = require("../../icons/scissors");
13
14
  const snowflake_1 = require("../../icons/snowflake");
@@ -30,6 +31,7 @@ const CollapsibleInspectorSection_1 = require("./CollapsibleInspectorSection");
30
31
  const common_1 = require("./common");
31
32
  const ConnectedCompositionsSection_1 = require("./ConnectedCompositionsSection");
32
33
  const SequenceInspectorHeader_1 = require("./SequenceInspectorHeader");
34
+ const SequenceWrapAction_1 = require("./SequenceWrapAction");
33
35
  const styles_1 = require("./styles");
34
36
  const use_track_for_selection_1 = require("./use-track-for-selection");
35
37
  const actionIconStyle = {
@@ -105,6 +107,11 @@ const SequenceSourceQuickActions = ({ selection, track, validatedSource }) => {
105
107
  : selection.nodePathInfo.numberOfSequencesWithThisNodePath > 1
106
108
  ? 'Programmatically duplicated media cannot be transcribed from source'
107
109
  : undefined;
110
+ const videoMattingDisabledReason = sourceActionsDisabled
111
+ ? 'Studio is read-only'
112
+ : selection.nodePathInfo.numberOfSequencesWithThisNodePath > 1
113
+ ? 'Programmatically duplicated videos cannot have their background removed from source'
114
+ : undefined;
108
115
  const onGenerateCaptions = (0, react_1.useCallback)(() => {
109
116
  if (transcriptionDisabledReason !== undefined || mediaSequence === null) {
110
117
  return;
@@ -130,6 +137,27 @@ const SequenceSourceQuickActions = ({ selection, track, validatedSource }) => {
130
137
  mediaSequence,
131
138
  transcriptionDisabledReason,
132
139
  ]);
140
+ const onRemoveBackground = (0, react_1.useCallback)(() => {
141
+ if (videoMattingDisabledReason !== undefined ||
142
+ track.sequence.type !== 'video') {
143
+ return;
144
+ }
145
+ const nodePath = selection.nodePathInfo.sequenceSubscriptionKey;
146
+ setSelectedModal({
147
+ type: 'video-matting',
148
+ src: track.sequence.src,
149
+ displayName: (0, public_output_name_1.getMediaFileName)(track.sequence.src, track.sequence.displayName),
150
+ target: {
151
+ fileName: nodePath.absolutePath,
152
+ nodePath,
153
+ },
154
+ });
155
+ }, [
156
+ selection.nodePathInfo,
157
+ setSelectedModal,
158
+ track.sequence,
159
+ videoMattingDisabledReason,
160
+ ]);
133
161
  const onDuplicate = (0, react_1.useCallback)(() => {
134
162
  if (sourceActionsDisabled) {
135
163
  return;
@@ -165,7 +193,7 @@ const SequenceSourceQuickActions = ({ selection, track, validatedSource }) => {
165
193
  (0, NotificationCenter_1.showNotification)(err.message, 4000);
166
194
  });
167
195
  }, [selection.nodePathInfo, splitVideoFromAudioDisabledReason]);
168
- return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [(freezeFrameMenuItem === null || freezeFrameMenuItem === void 0 ? void 0 : freezeFrameMenuItem.type) === 'item' ? (jsx_runtime_1.jsx(common_1.InspectorQuickAction, { disabled: Boolean(freezeFrameMenuItem.disabled), onClick: () => freezeFrameMenuItem.onClick(freezeFrameMenuItem.id, null), renderIcon: (color) => (jsx_runtime_1.jsx(snowflake_1.SnowflakeIcon, { style: largeActionIconStyle, color: color })), children: freezeFrameMenuItem.label })) : null, track.sequence.type === 'video' ? (jsx_runtime_1.jsx(common_1.InspectorQuickAction, { disabled: splitVideoFromAudioDisabledReason !== undefined, onClick: onSplitVideoFromAudio, title: splitVideoFromAudioDisabledReason, renderIcon: (color) => (jsx_runtime_1.jsx(audio_1.AudioIcon, { style: actionIconStyle, color: color })), children: "Split video from audio" })) : null, mediaSequence !== null && (mediaMetadata === null || mediaMetadata === void 0 ? void 0 : mediaMetadata.hasAudioTrack) !== false ? (jsx_runtime_1.jsx(common_1.InspectorQuickAction, { disabled: transcriptionDisabledReason !== undefined, onClick: onGenerateCaptions, title: transcriptionDisabledReason, renderIcon: (color) => (jsx_runtime_1.jsx(transcription_1.TranscriptionIcon, { style: actionIconStyle, color: color })), children: "Generate captions" })) : null, jsx_runtime_1.jsx(common_1.InspectorQuickAction, { disabled: sourceActionsDisabled, onClick: onDuplicate, renderIcon: (color) => (jsx_runtime_1.jsx(duplicate_1.DuplicateIcon, { style: largeActionIconStyle, color: color })), children: "Duplicate" }), jsx_runtime_1.jsx(common_1.InspectorQuickAction, { disabled: sourceActionsDisabled, onClick: onDelete, renderIcon: (color) => (jsx_runtime_1.jsx(trash_1.TrashIcon, { style: actionIconStyle, color: color })), children: "Delete" })] }));
196
+ return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [(freezeFrameMenuItem === null || freezeFrameMenuItem === void 0 ? void 0 : freezeFrameMenuItem.type) === 'item' ? (jsx_runtime_1.jsx(common_1.InspectorQuickAction, { disabled: Boolean(freezeFrameMenuItem.disabled), onClick: () => freezeFrameMenuItem.onClick(freezeFrameMenuItem.id, null), renderIcon: (color) => (jsx_runtime_1.jsx(snowflake_1.SnowflakeIcon, { style: largeActionIconStyle, color: color })), children: freezeFrameMenuItem.label })) : null, track.sequence.type === 'video' ? (jsx_runtime_1.jsx(common_1.InspectorQuickAction, { disabled: videoMattingDisabledReason !== undefined, onClick: onRemoveBackground, title: videoMattingDisabledReason, renderIcon: (color) => (jsx_runtime_1.jsx(background_removal_1.BackgroundRemovalIcon, { style: actionIconStyle, color: color })), children: "Remove background" })) : null, track.sequence.type === 'video' ? (jsx_runtime_1.jsx(common_1.InspectorQuickAction, { disabled: splitVideoFromAudioDisabledReason !== undefined, onClick: onSplitVideoFromAudio, title: splitVideoFromAudioDisabledReason, renderIcon: (color) => (jsx_runtime_1.jsx(audio_1.AudioIcon, { style: actionIconStyle, color: color })), children: "Split video from audio" })) : null, mediaSequence !== null && (mediaMetadata === null || mediaMetadata === void 0 ? void 0 : mediaMetadata.hasAudioTrack) !== false ? (jsx_runtime_1.jsx(common_1.InspectorQuickAction, { disabled: transcriptionDisabledReason !== undefined, onClick: onGenerateCaptions, title: transcriptionDisabledReason, renderIcon: (color) => (jsx_runtime_1.jsx(transcription_1.TranscriptionIcon, { style: actionIconStyle, color: color })), children: "Generate captions" })) : null, jsx_runtime_1.jsx(common_1.InspectorQuickAction, { disabled: sourceActionsDisabled, onClick: onDuplicate, renderIcon: (color) => (jsx_runtime_1.jsx(duplicate_1.DuplicateIcon, { style: largeActionIconStyle, color: color })), children: "Duplicate" }), jsx_runtime_1.jsx(SequenceWrapAction_1.SequenceWrapAction, { nodePathInfo: selection.nodePathInfo, sequence: track.sequence, sourceActionsDisabled: sourceActionsDisabled }), jsx_runtime_1.jsx(common_1.InspectorQuickAction, { disabled: sourceActionsDisabled, onClick: onDelete, renderIcon: (color) => (jsx_runtime_1.jsx(trash_1.TrashIcon, { style: actionIconStyle, color: color })), children: "Delete" })] }));
169
197
  };
170
198
  const SequenceExpandedInspector = ({ track, readOnlyStudio }) => {
171
199
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
@@ -210,7 +238,7 @@ const SequenceExpandedInspector = ({ track, readOnlyStudio }) => {
210
238
  return jsx_runtime_1.jsx(common_1.InspectorMessage, { children: "Sequence inspector unavailable" });
211
239
  }
212
240
  return (jsx_runtime_1.jsxs("div", { style: styles_1.selectedContainer, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, onPointerDown: selectSequenceOnInspectorPointerDown, children: [
213
- jsx_runtime_1.jsx(SequenceInspectorHeader_1.SequenceInspectorHeader, { sourceLocation: sourceLocation, track: track }, stackKey !== null && stackKey !== void 0 ? stackKey : track.sequence.id), jsx_runtime_1.jsx(SequenceInspectorHeader_1.SequenceInspectorDuplicationSection, { track: track }), connectedCompositions.length > 0 ? (jsx_runtime_1.jsx(ConnectedCompositionsSection_1.ConnectedCompositionsSection, { connectedCompositions: connectedCompositions })) : null, validatedLocation ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [jsx_runtime_1.jsx(InspectorSequenceSection_1.InspectorSequenceSection, { sequence: track.sequence, readOnlyStudio: readOnlyStudio, validatedLocation: validatedLocation, nodePathInfo: track.nodePathInfo, keyframeDisplayOffset: track.keyframeDisplayOffset, renderTransformControls: () => jsx_runtime_1.jsx(AlignmentControls_1.AlignmentControls, { track: track }) }), jsx_runtime_1.jsx(CollapsibleInspectorSection_1.CollapsibleInspectorSection, { collapsible: true, label: "Actions", sectionId: "sequence-actions", children: jsx_runtime_1.jsxs(common_1.InspectorQuickActionsSection, { children: [
241
+ jsx_runtime_1.jsx(SequenceInspectorHeader_1.SequenceInspectorHeader, { sourceLocation: sourceLocation, track: track }, stackKey !== null && stackKey !== void 0 ? stackKey : track.sequence.id), jsx_runtime_1.jsx(SequenceInspectorHeader_1.SequenceInspectorDuplicationSection, { track: track }), connectedCompositions.length > 0 ? (jsx_runtime_1.jsx(ConnectedCompositionsSection_1.ConnectedCompositionsSection, { connectedCompositions: connectedCompositions })) : null, validatedLocation ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [jsx_runtime_1.jsx(InspectorSequenceSection_1.InspectorSequenceSection, { sequence: track.sequence, readOnlyStudio: readOnlyStudio, validatedLocation: validatedLocation, nodePathInfo: track.nodePathInfo, keyframeDisplayOffset: track.keyframeDisplayOffset, keyframePlaybackRate: track.keyframePlaybackRate, renderTransformControls: () => jsx_runtime_1.jsx(AlignmentControls_1.AlignmentControls, { track: track }) }), jsx_runtime_1.jsx(CollapsibleInspectorSection_1.CollapsibleInspectorSection, { collapsible: true, label: "Actions", sectionId: "sequence-actions", children: jsx_runtime_1.jsxs(common_1.InspectorQuickActionsSection, { children: [
214
242
  jsx_runtime_1.jsx(SplitSequenceQuickAction, { selection: sequenceSelection, track: track }), jsx_runtime_1.jsx(SequenceSourceQuickActions, { selection: sequenceSelection, track: track, validatedSource: validatedLocation.source })
215
243
  ] }) })
216
244
  ] })) : (jsx_runtime_1.jsx(common_1.InspectorMessage, { children: "Source controls unavailable" }))] }));
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ import type { SequenceNodePathInfo } from '../../helpers/get-timeline-sequence-sort-key';
3
+ import type { TimelineTrackData } from '../../helpers/get-timeline-sequence-sort-key';
4
+ export declare const SequenceWrapAction: React.FC<{
5
+ readonly nodePathInfo: SequenceNodePathInfo;
6
+ readonly sequence: TimelineTrackData['sequence'];
7
+ readonly sourceActionsDisabled: boolean;
8
+ }>;
@@ -0,0 +1,151 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SequenceWrapAction = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const remotion_1 = require("remotion");
7
+ const colors_1 = require("../../helpers/colors");
8
+ const caret_1 = require("../../icons/caret");
9
+ const wrap_1 = require("../../icons/wrap");
10
+ const InspectorPanelLayout_1 = require("../InspectorPanelLayout");
11
+ const NotificationCenter_1 = require("../Notifications/NotificationCenter");
12
+ const SegmentedButton_1 = require("../SegmentedButton");
13
+ const wrap_jsx_node_api_1 = require("../wrap-jsx-node-api");
14
+ const wrapperNames = ['AbsoluteFill', 'Sequence', 'HtmlInCanvas'];
15
+ const buttonStyle = {
16
+ borderRadius: 4,
17
+ height: 28,
18
+ margin: '0 4px',
19
+ width: 'calc(100% - 8px)',
20
+ };
21
+ const segmentStyle = {
22
+ fontSize: 13,
23
+ gap: 8,
24
+ justifyContent: 'flex-start',
25
+ padding: `0 ${InspectorPanelLayout_1.INSPECTOR_PANEL_HORIZONTAL_PADDING - 4}px`,
26
+ width: '100%',
27
+ };
28
+ const iconStyle = { height: 22, width: 22 };
29
+ const iconContainerStyle = {
30
+ flexShrink: 0,
31
+ height: 22,
32
+ marginLeft: -2,
33
+ marginRight: -2,
34
+ width: 22,
35
+ };
36
+ const labelStyle = {
37
+ flex: 1,
38
+ fontFamily: 'sans-serif',
39
+ fontSize: 13,
40
+ lineHeight: '18px',
41
+ minWidth: 0,
42
+ overflow: 'hidden',
43
+ textAlign: 'left',
44
+ textOverflow: 'ellipsis',
45
+ userSelect: 'none',
46
+ WebkitUserSelect: 'none',
47
+ whiteSpace: 'nowrap',
48
+ };
49
+ const caretStyle = {
50
+ display: 'flex',
51
+ flexShrink: 0,
52
+ height: 12,
53
+ width: 12,
54
+ };
55
+ const SequenceWrapAction = ({ nodePathInfo, sequence, sourceActionsDisabled }) => {
56
+ const { width, height } = (0, remotion_1.useVideoConfig)();
57
+ const nodePathKey = JSON.stringify(nodePathInfo.sequenceSubscriptionKey);
58
+ const [eligibility, setEligibility] = (0, react_1.useState)(null);
59
+ const [busy, setBusy] = (0, react_1.useState)(false);
60
+ (0, react_1.useEffect)(() => {
61
+ setEligibility(null);
62
+ if (sourceActionsDisabled) {
63
+ return;
64
+ }
65
+ let cancelled = false;
66
+ const nodePath = JSON.parse(nodePathKey);
67
+ (0, wrap_jsx_node_api_1.wrapJsxNode)({
68
+ fileName: nodePath.absolutePath,
69
+ nodePath: nodePath.nodePath,
70
+ wrapper: null,
71
+ width: null,
72
+ height: null,
73
+ })
74
+ .then((result) => {
75
+ if (!cancelled && result.success) {
76
+ setEligibility({
77
+ canWrap: result.canWrap,
78
+ canWrapHtmlInCanvas: result.canWrapHtmlInCanvas,
79
+ });
80
+ }
81
+ })
82
+ .catch(() => undefined);
83
+ return () => {
84
+ cancelled = true;
85
+ };
86
+ }, [nodePathKey, sequence, sourceActionsDisabled]);
87
+ const onWrap = (0, react_1.useCallback)((wrapper) => {
88
+ if (busy || sourceActionsDisabled || !(eligibility === null || eligibility === void 0 ? void 0 : eligibility.canWrap)) {
89
+ return;
90
+ }
91
+ setBusy(true);
92
+ const nodePath = JSON.parse(nodePathKey);
93
+ (0, wrap_jsx_node_api_1.wrapJsxNode)({
94
+ fileName: nodePath.absolutePath,
95
+ nodePath: nodePath.nodePath,
96
+ wrapper,
97
+ width,
98
+ height,
99
+ })
100
+ .then((result) => {
101
+ if (!result.success) {
102
+ (0, NotificationCenter_1.showNotification)(result.reason, 4000);
103
+ }
104
+ })
105
+ .catch((error) => {
106
+ (0, NotificationCenter_1.showNotification)(error.message, 4000);
107
+ })
108
+ .finally(() => setBusy(false));
109
+ }, [busy, eligibility, height, nodePathKey, sourceActionsDisabled, width]);
110
+ const values = (0, react_1.useMemo)(() => wrapperNames.map((wrapper) => ({
111
+ type: 'item',
112
+ id: wrapper,
113
+ label: `<${wrapper}>`,
114
+ value: wrapper,
115
+ onClick: () => onWrap(wrapper),
116
+ keyHint: null,
117
+ leftItem: null,
118
+ subMenu: null,
119
+ quickSwitcherLabel: null,
120
+ disabled: busy ||
121
+ (wrapper === 'HtmlInCanvas' &&
122
+ (!(eligibility === null || eligibility === void 0 ? void 0 : eligibility.canWrapHtmlInCanvas) || !(0, remotion_1.isHtmlInCanvasSupported)())),
123
+ })), [busy, eligibility, onWrap]);
124
+ const segments = (0, react_1.useMemo)(() => [
125
+ {
126
+ ariaLabel: 'Wrap',
127
+ buttonId: null,
128
+ disabled: busy,
129
+ idleColor: colors_1.LIGHT_TEXT,
130
+ leaveLeftSpace: false,
131
+ onOpenChange: null,
132
+ renderContent: (color) => (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
133
+ jsx_runtime_1.jsx("span", { style: iconContainerStyle, children: jsx_runtime_1.jsx(wrap_1.WrapIcon, { color: color, style: iconStyle }) }), jsx_runtime_1.jsx("span", { style: labelStyle, children: "Wrap" }), jsx_runtime_1.jsx("span", { style: caretStyle, children: jsx_runtime_1.jsx(caret_1.CaretDown, { color: color }) })
134
+ ] })),
135
+ segmentId: 'wrap',
136
+ selectedId: null,
137
+ style: segmentStyle,
138
+ title: nodePathInfo.numberOfSequencesWithThisNodePath > 1
139
+ ? `Wrap all ${nodePathInfo.numberOfSequencesWithThisNodePath} instances of this JSX element`
140
+ : 'Wrap this JSX element',
141
+ tooltipLabel: null,
142
+ type: 'menu',
143
+ values,
144
+ },
145
+ ], [busy, nodePathInfo.numberOfSequencesWithThisNodePath, values]);
146
+ if (!(eligibility === null || eligibility === void 0 ? void 0 : eligibility.canWrap) || sourceActionsDisabled) {
147
+ return null;
148
+ }
149
+ return (jsx_runtime_1.jsx(SegmentedButton_1.SegmentedButton, { segments: segments, style: buttonStyle, title: null }));
150
+ };
151
+ exports.SequenceWrapAction = SequenceWrapAction;
@@ -1,7 +1,8 @@
1
1
  import type { CanUpdateSequencePropStatusKeyframed } from 'remotion';
2
2
  import type { SequenceNodePathInfo } from '../../helpers/get-timeline-sequence-sort-key';
3
- export declare const getEasingSelectionFromCurrentKeyframes: ({ keyframeDisplayOffset, nodePathInfo, propStatus, segmentIndex, }: {
3
+ export declare const getEasingSelectionFromCurrentKeyframes: ({ keyframeDisplayOffset, keyframePlaybackRate, nodePathInfo, propStatus, segmentIndex, }: {
4
4
  readonly keyframeDisplayOffset: number;
5
+ readonly keyframePlaybackRate: number;
5
6
  readonly nodePathInfo: SequenceNodePathInfo;
6
7
  readonly propStatus: CanUpdateSequencePropStatusKeyframed;
7
8
  readonly segmentIndex: number;
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getEasingSelectionFromCurrentKeyframes = void 0;
4
4
  const get_timeline_keyframes_1 = require("../Timeline/get-timeline-keyframes");
5
- const getEasingSelectionFromCurrentKeyframes = ({ keyframeDisplayOffset, nodePathInfo, propStatus, segmentIndex, }) => {
5
+ const getEasingSelectionFromCurrentKeyframes = ({ keyframeDisplayOffset, keyframePlaybackRate, nodePathInfo, propStatus, segmentIndex, }) => {
6
6
  const fromKeyframe = propStatus.keyframes[segmentIndex];
7
7
  const toKeyframe = propStatus.keyframes[segmentIndex + 1];
8
8
  if (!fromKeyframe || !toKeyframe) {
@@ -11,12 +11,13 @@ const getEasingSelectionFromCurrentKeyframes = ({ keyframeDisplayOffset, nodePat
11
11
  const resolvedKeyframeDisplayOffset = (0, get_timeline_keyframes_1.getKeyframeDisplayOffset)({
12
12
  propStatus,
13
13
  keyframeDisplayOffset,
14
+ keyframePlaybackRate,
14
15
  });
15
16
  return {
16
17
  type: 'easing',
17
18
  nodePathInfo,
18
- fromFrame: fromKeyframe.frame + resolvedKeyframeDisplayOffset,
19
- toFrame: toKeyframe.frame + resolvedKeyframeDisplayOffset,
19
+ fromFrame: fromKeyframe.frame / keyframePlaybackRate + resolvedKeyframeDisplayOffset,
20
+ toFrame: toKeyframe.frame / keyframePlaybackRate + resolvedKeyframeDisplayOffset,
20
21
  segmentIndex,
21
22
  };
22
23
  };
@@ -2,7 +2,8 @@ export declare const clampInspectorKeyframeDisplayFrame: ({ durationInFrames, fr
2
2
  readonly durationInFrames: number;
3
3
  readonly frame: number;
4
4
  }) => number;
5
- export declare const getInspectorKeyframeSourceFrame: ({ displayFrame, keyframeDisplayOffset, }: {
5
+ export declare const getInspectorKeyframeSourceFrame: ({ displayFrame, keyframeDisplayOffset, keyframePlaybackRate, }: {
6
6
  readonly displayFrame: number;
7
7
  readonly keyframeDisplayOffset: number;
8
+ readonly keyframePlaybackRate: number;
8
9
  }) => number;
@@ -8,7 +8,7 @@ const clampInspectorKeyframeDisplayFrame = ({ durationInFrames, frame, }) => {
8
8
  return Math.min(Math.max(Math.round(frame), 0), durationInFrames - 1);
9
9
  };
10
10
  exports.clampInspectorKeyframeDisplayFrame = clampInspectorKeyframeDisplayFrame;
11
- const getInspectorKeyframeSourceFrame = ({ displayFrame, keyframeDisplayOffset, }) => {
12
- return displayFrame - keyframeDisplayOffset;
11
+ const getInspectorKeyframeSourceFrame = ({ displayFrame, keyframeDisplayOffset, keyframePlaybackRate, }) => {
12
+ return (displayFrame - keyframeDisplayOffset) * keyframePlaybackRate;
13
13
  };
14
14
  exports.getInspectorKeyframeSourceFrame = getInspectorKeyframeSourceFrame;