@remotion/studio 4.0.475 → 4.0.477

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 (88) hide show
  1. package/dist/components/Canvas.js +40 -1
  2. package/dist/components/ColorPicker/ColorPickerPopup.d.ts +6 -0
  3. package/dist/components/ColorPicker/ColorPickerPopup.js +11 -6
  4. package/dist/components/ControlButton.d.ts +1 -0
  5. package/dist/components/ControlButton.js +7 -2
  6. package/dist/components/EditorGuides/Guide.js +122 -20
  7. package/dist/components/EditorRuler/Ruler.js +21 -15
  8. package/dist/components/EditorRuler/index.js +18 -10
  9. package/dist/components/GlobalKeybindings.js +12 -0
  10. package/dist/components/KeyboardShortcutsExplainer.js +24 -0
  11. package/dist/components/NewComposition/InputDragger.d.ts +6 -0
  12. package/dist/components/NewComposition/InputDragger.js +40 -14
  13. package/dist/components/NewComposition/RenameComposition.js +8 -1
  14. package/dist/components/NewComposition/RenameFolder.js +8 -1
  15. package/dist/components/NewComposition/RenameStaticFile.js +11 -1
  16. package/dist/components/Notifications/Notification.js +5 -4
  17. package/dist/components/Notifications/NotificationCenter.js +1 -1
  18. package/dist/components/ObserveDefaultPropsContext.js +6 -2
  19. package/dist/components/OutlineToggle.js +1 -1
  20. package/dist/components/PlayPause.js +22 -66
  21. package/dist/components/PreviewToolbar.js +15 -1
  22. package/dist/components/RenderModal/RenderModalJSONPropsEditor.js +2 -1
  23. package/dist/components/SelectedOutlineElement.d.ts +17 -0
  24. package/dist/components/SelectedOutlineElement.js +938 -0
  25. package/dist/components/SelectedOutlineOverlay.d.ts +4 -174
  26. package/dist/components/SelectedOutlineOverlay.js +310 -1392
  27. package/dist/components/SelectedOutlineUvControls.js +1 -1
  28. package/dist/components/ShowGuidesProvider.js +4 -4
  29. package/dist/components/Timeline/SubscribeToNodePaths.d.ts +2 -1
  30. package/dist/components/Timeline/SubscribeToNodePaths.js +2 -1
  31. package/dist/components/Timeline/Timeline.js +3 -1
  32. package/dist/components/Timeline/TimelineClipboardKeybindings.js +9 -10
  33. package/dist/components/Timeline/TimelineDeleteKeybindings.js +15 -4
  34. package/dist/components/Timeline/TimelineKeyframeEasingLine.js +7 -11
  35. package/dist/components/Timeline/TimelineList.js +1 -1
  36. package/dist/components/Timeline/TimelineRotationField.js +17 -17
  37. package/dist/components/Timeline/TimelineScaleField.js +1 -1
  38. package/dist/components/Timeline/TimelineSelection.d.ts +27 -13
  39. package/dist/components/Timeline/TimelineSelection.js +47 -28
  40. package/dist/components/Timeline/TimelineSequence.js +169 -8
  41. package/dist/components/Timeline/TimelineSequenceFrame.d.ts +1 -0
  42. package/dist/components/Timeline/TimelineSequenceFrame.js +17 -6
  43. package/dist/components/Timeline/TimelineSequenceItem.d.ts +1 -0
  44. package/dist/components/Timeline/TimelineSequenceItem.js +294 -142
  45. package/dist/components/Timeline/TimelineSequenceName.d.ts +4 -2
  46. package/dist/components/Timeline/TimelineSequenceName.js +67 -2
  47. package/dist/components/Timeline/TimelineTransformOriginField.js +1 -1
  48. package/dist/components/Timeline/TimelineTranslateField.js +1 -1
  49. package/dist/components/Timeline/TimelineUvCoordinateField.js +1 -1
  50. package/dist/components/Timeline/delete-selected-timeline-item.js +4 -0
  51. package/dist/components/Timeline/disable-sequence-interactivity.d.ts +8 -0
  52. package/dist/components/Timeline/disable-sequence-interactivity.js +24 -0
  53. package/dist/components/Timeline/duplicate-selected-timeline-item.d.ts +1 -2
  54. package/dist/components/Timeline/get-sequence-context-menu-items.d.ts +20 -0
  55. package/dist/components/Timeline/get-sequence-context-menu-items.js +160 -0
  56. package/dist/components/Timeline/reset-selected-timeline-props.js +2 -2
  57. package/dist/components/Timeline/sequence-props-subscription-store.d.ts +2 -1
  58. package/dist/components/Timeline/sequence-props-subscription-store.js +11 -3
  59. package/dist/components/Timeline/should-clear-selection-on-pointer-down.d.ts +2 -0
  60. package/dist/components/Timeline/should-clear-selection-on-pointer-down.js +16 -2
  61. package/dist/components/Timeline/timeline-rotation-utils.d.ts +1 -1
  62. package/dist/components/Timeline/timeline-rotation-utils.js +4 -2
  63. package/dist/components/Timeline/update-selected-easing.d.ts +4 -6
  64. package/dist/components/Timeline/use-sequence-props-subscription.d.ts +2 -1
  65. package/dist/components/Timeline/use-sequence-props-subscription.js +3 -1
  66. package/dist/components/Timeline/use-timeline-keyframe-drag.d.ts +37 -1
  67. package/dist/components/Timeline/use-timeline-keyframe-drag.js +290 -14
  68. package/dist/components/import-assets.d.ts +36 -8
  69. package/dist/components/import-assets.js +170 -10
  70. package/dist/components/selected-outline-drag.d.ts +117 -0
  71. package/dist/components/selected-outline-drag.js +427 -0
  72. package/dist/components/selected-outline-measurement.d.ts +67 -0
  73. package/dist/components/selected-outline-measurement.js +355 -0
  74. package/dist/components/selected-outline-types.d.ts +121 -0
  75. package/dist/components/selected-outline-types.js +15 -0
  76. package/dist/components/selected-outline-uv.d.ts +1 -0
  77. package/dist/components/selected-outline-uv.js +12 -0
  78. package/dist/esm/{chunk-qaqqvw4q.js → chunk-t8fjnw2d.js} +14059 -12029
  79. package/dist/esm/internals.mjs +14059 -12029
  80. package/dist/esm/previewEntry.mjs +14066 -12036
  81. package/dist/esm/renderEntry.mjs +1 -1
  82. package/dist/helpers/editor-guide-selection.d.ts +31 -0
  83. package/dist/helpers/editor-guide-selection.js +58 -0
  84. package/dist/helpers/editor-ruler.d.ts +3 -3
  85. package/dist/helpers/editor-ruler.js +16 -18
  86. package/dist/state/editor-guides.d.ts +2 -2
  87. package/dist/state/editor-guides.js +2 -2
  88. package/package.json +11 -11
@@ -37,12 +37,24 @@ exports.TimelineSequence = void 0;
37
37
  const jsx_runtime_1 = require("react/jsx-runtime");
38
38
  const react_1 = __importStar(require("react"));
39
39
  const remotion_1 = require("remotion");
40
+ const client_id_1 = require("../../helpers/client-id");
40
41
  const colors_1 = require("../../helpers/colors");
42
+ const format_file_location_1 = require("../../helpers/format-file-location");
41
43
  const get_timeline_sequence_layout_1 = require("../../helpers/get-timeline-sequence-layout");
44
+ const open_in_editor_1 = require("../../helpers/open-in-editor");
42
45
  const timeline_layout_1 = require("../../helpers/timeline-layout");
43
46
  const use_max_media_duration_1 = require("../../helpers/use-max-media-duration");
44
47
  const AudioWaveform_1 = require("../AudioWaveform");
48
+ const call_api_1 = require("../call-api");
49
+ const ConfirmationDialog_1 = require("../ConfirmationDialog");
50
+ const ContextMenu_1 = require("../ContextMenu");
51
+ const NotificationCenter_1 = require("../Notifications/NotificationCenter");
52
+ const use_select_asset_1 = require("../use-select-asset");
53
+ const disable_sequence_interactivity_1 = require("./disable-sequence-interactivity");
54
+ const duplicate_selected_timeline_item_1 = require("./duplicate-selected-timeline-item");
55
+ const get_sequence_context_menu_items_1 = require("./get-sequence-context-menu-items");
45
56
  const LoopedTimelineIndicators_1 = require("./LoopedTimelineIndicators");
57
+ const timeline_asset_link_1 = require("./timeline-asset-link");
46
58
  const TimelineImageInfo_1 = require("./TimelineImageInfo");
47
59
  const TimelineSelection_1 = require("./TimelineSelection");
48
60
  const TimelineSequenceFrame_1 = require("./TimelineSequenceFrame");
@@ -60,7 +72,7 @@ const TimelineSequenceFn = ({ s, nodePathInfo, sequenceFrameOffset }) => {
60
72
  }
61
73
  return (jsx_runtime_1.jsx(TimelineSequenceInner, { windowWidth: windowWidth, s: s, nodePathInfo: nodePathInfo, sequenceFrameOffset: sequenceFrameOffset }));
62
74
  };
63
- const TimelineSequenceCurrentFrame = ({ s, displayDurationInFrames, premountWidth, postmountWidth, style, children, nodePathInfo, sequenceFrameOffset, fromCanUpdate, onMoveDragPointerDown, }) => {
75
+ const TimelineSequenceCurrentFrame = ({ s, displayDurationInFrames, premountWidth, postmountWidth, style, children, nodePathInfo, sequenceFrameOffset, fromCanUpdate, frozenFrame, onMoveDragPointerDown, }) => {
64
76
  var _a, _b;
65
77
  const ref = (0, react_1.useRef)(null);
66
78
  const { onSelect, selectable, selected, selectionItem } = (0, TimelineSelection_1.useTimelineRowSelection)(nodePathInfo);
@@ -135,16 +147,16 @@ const TimelineSequenceCurrentFrame = ({ s, displayDurationInFrames, premountWidt
135
147
  height: '100%',
136
148
  display: 'flex',
137
149
  alignItems: 'center',
138
- }, children: jsx_runtime_1.jsx(TimelineSequenceFrame_1.TimelineSequenceFrame, { premounted: isPremounting, postmounted: isPostmounting ? s.duration - 1 : null, roundedFrame: roundedFrame }) })) : null] }));
150
+ }, children: jsx_runtime_1.jsx(TimelineSequenceFrame_1.TimelineSequenceFrame, { premounted: isPremounting, postmounted: isPostmounting ? s.duration - 1 : null, roundedFrame: roundedFrame, frozenFrame: frozenFrame }) })) : null] }));
139
151
  };
140
152
  const TimelineSequenceInner = ({ s, windowWidth, nodePathInfo, sequenceFrameOffset }) => {
141
153
  // If a duration is 1, it is essentially a still and it should have width 0
142
154
  // Some compositions may not be longer than their media duration,
143
155
  // if that is the case, it needs to be asynchronously determined
144
- var _a, _b;
145
- var _c, _d, _e, _f;
156
+ var _a, _b, _c;
157
+ var _d, _e, _f, _g;
146
158
  const video = remotion_1.Internals.useVideo();
147
- 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);
159
+ const maxMediaDuration = (0, use_max_media_duration_1.useMaxMediaDuration)(s, (_d = video === null || video === void 0 ? void 0 : video.fps) !== null && _d !== void 0 ? _d : 30);
148
160
  const effectiveMaxMediaDuration = s.loopDisplay ? null : maxMediaDuration;
149
161
  const originalLocation = (0, use_resolved_stack_react_to_change_1.useResolveStackAndReactToChange)(s.getStack);
150
162
  const validatedLocation = (0, react_1.useMemo)(() => {
@@ -161,7 +173,7 @@ const TimelineSequenceInner = ({ s, windowWidth, nodePathInfo, sequenceFrameOffs
161
173
  };
162
174
  }, [originalLocation]);
163
175
  const { propStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModePropStatusesContext);
164
- const nodePath = (_d = nodePathInfo === null || nodePathInfo === void 0 ? void 0 : nodePathInfo.sequenceSubscriptionKey) !== null && _d !== void 0 ? _d : null;
176
+ const nodePath = (_e = nodePathInfo === null || nodePathInfo === void 0 ? void 0 : nodePathInfo.sequenceSubscriptionKey) !== null && _e !== void 0 ? _e : null;
165
177
  const propStatusesForOverride = (0, react_1.useMemo)(() => {
166
178
  return nodePath
167
179
  ? remotion_1.Internals.getPropStatusesCtx(propStatuses, nodePath)
@@ -169,10 +181,158 @@ const TimelineSequenceInner = ({ s, windowWidth, nodePathInfo, sequenceFrameOffs
169
181
  }, [propStatuses, nodePath]);
170
182
  const durationCanUpdate = Boolean(((_a = propStatusesForOverride === null || propStatusesForOverride === void 0 ? void 0 : propStatusesForOverride.durationInFrames) === null || _a === void 0 ? void 0 : _a.status) === 'static');
171
183
  const fromCanUpdate = Boolean(((_b = propStatusesForOverride === null || propStatusesForOverride === void 0 ? void 0 : propStatusesForOverride.from) === null || _b === void 0 ? void 0 : _b.status) === 'static');
184
+ const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
185
+ const previewConnected = previewServerState.type === 'connected';
186
+ const { setPropStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
187
+ const selectAsset = (0, use_select_asset_1.useSelectAsset)();
188
+ const confirm = (0, ConfirmationDialog_1.useConfirmationDialog)();
189
+ const { onSelect, selectable } = (0, TimelineSelection_1.useTimelineRowSelection)(nodePathInfo);
190
+ const fileLocation = (0, react_1.useMemo)(() => (0, format_file_location_1.formatFileLocation)({
191
+ location: originalLocation,
192
+ root: window.remotion_cwd,
193
+ }), [originalLocation]);
194
+ const canOpenInEditor = Boolean(window.remotion_editorName && previewConnected && originalLocation);
195
+ const openInEditor = (0, react_1.useCallback)(() => {
196
+ if (!canOpenInEditor || !originalLocation) {
197
+ return;
198
+ }
199
+ (0, open_in_editor_1.openOriginalPositionInEditor)(originalLocation).catch((err) => {
200
+ (0, NotificationCenter_1.showNotification)(err.message, 2000);
201
+ });
202
+ }, [canOpenInEditor, originalLocation]);
203
+ const canDeleteFromSource = Boolean(nodePath && (validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source));
204
+ const deleteDisabled = !previewConnected || !s.controls || !canDeleteFromSource;
205
+ const duplicateDisabled = deleteDisabled;
206
+ const disableInteractivityDisabled = !previewConnected ||
207
+ !s.showInTimeline ||
208
+ !nodePath ||
209
+ !(validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source);
210
+ const mediaSrc = s.type === 'audio' || s.type === 'video' || s.type === 'image'
211
+ ? s.src
212
+ : null;
213
+ const assetLinkInfo = (0, react_1.useMemo)(() => (mediaSrc ? (0, timeline_asset_link_1.getTimelineAssetLinkInfo)(mediaSrc) : null), [mediaSrc]);
214
+ const onDuplicateSequenceFromSource = (0, react_1.useCallback)(() => {
215
+ if (!(validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source) || !nodePathInfo || duplicateDisabled) {
216
+ return;
217
+ }
218
+ (0, duplicate_selected_timeline_item_1.duplicateSequencesFromSource)([nodePathInfo], confirm).catch(() => undefined);
219
+ }, [confirm, duplicateDisabled, nodePathInfo, validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source]);
220
+ const onDeleteSequenceFromSource = (0, react_1.useCallback)(async () => {
221
+ if (!(validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source) || !nodePath || deleteDisabled) {
222
+ return;
223
+ }
224
+ if (nodePathInfo && nodePathInfo.numberOfSequencesWithThisNodePath > 1) {
225
+ const shouldDelete = await confirm({
226
+ title: 'Delete sequence?',
227
+ message: 'This sequence is programmatically duplicated ' +
228
+ nodePathInfo.numberOfSequencesWithThisNodePath +
229
+ ' times in the code. Deleting removes all instances. Continue?',
230
+ confirmLabel: 'Delete',
231
+ });
232
+ if (!shouldDelete) {
233
+ return;
234
+ }
235
+ }
236
+ try {
237
+ const result = await (0, call_api_1.callApi)('/api/delete-jsx-node', {
238
+ nodes: [
239
+ {
240
+ fileName: validatedLocation.source,
241
+ nodePath: nodePath.nodePath,
242
+ },
243
+ ],
244
+ });
245
+ if (result.success) {
246
+ (0, NotificationCenter_1.showNotification)('Removed sequence from source file', 2000);
247
+ }
248
+ else {
249
+ (0, NotificationCenter_1.showNotification)(result.reason, 4000);
250
+ }
251
+ }
252
+ catch (err) {
253
+ (0, NotificationCenter_1.showNotification)(err.message, 4000);
254
+ }
255
+ }, [
256
+ confirm,
257
+ deleteDisabled,
258
+ nodePath,
259
+ nodePathInfo,
260
+ validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source,
261
+ ]);
262
+ const onDisableSequenceInteractivity = (0, react_1.useCallback)(() => {
263
+ if (disableInteractivityDisabled ||
264
+ !nodePath ||
265
+ !(validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source) ||
266
+ previewServerState.type !== 'connected') {
267
+ return;
268
+ }
269
+ (0, disable_sequence_interactivity_1.disableSequenceInteractivity)({
270
+ fileName: validatedLocation.source,
271
+ nodePath,
272
+ setPropStatuses,
273
+ clientId: previewServerState.clientId,
274
+ });
275
+ }, [
276
+ disableInteractivityDisabled,
277
+ nodePath,
278
+ previewServerState,
279
+ setPropStatuses,
280
+ validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source,
281
+ ]);
282
+ const contextMenuValues = (0, react_1.useMemo)(() => {
283
+ if (!previewConnected) {
284
+ return [];
285
+ }
286
+ return (0, get_sequence_context_menu_items_1.getSequenceContextMenuItems)({
287
+ assetLinkInfo,
288
+ canOpenInEditor,
289
+ deleteDisabled,
290
+ disableInteractivityDisabled,
291
+ duplicateDisabled,
292
+ fileLocation,
293
+ includeSourceEditItems: true,
294
+ onDeleteSequenceFromSource,
295
+ onDisableSequenceInteractivity,
296
+ onDuplicateSequenceFromSource,
297
+ openInEditor,
298
+ originalLocation,
299
+ selectAsset,
300
+ sequence: s,
301
+ });
302
+ }, [
303
+ assetLinkInfo,
304
+ canOpenInEditor,
305
+ deleteDisabled,
306
+ disableInteractivityDisabled,
307
+ duplicateDisabled,
308
+ fileLocation,
309
+ onDeleteSequenceFromSource,
310
+ onDisableSequenceInteractivity,
311
+ onDuplicateSequenceFromSource,
312
+ openInEditor,
313
+ originalLocation,
314
+ previewConnected,
315
+ s,
316
+ selectAsset,
317
+ ]);
318
+ const onContextMenuOpen = (0, react_1.useCallback)(() => {
319
+ if (selectable) {
320
+ onSelect({ shiftKey: false, toggleKey: false });
321
+ }
322
+ }, [onSelect, selectable]);
323
+ const freezeStatus = propStatusesForOverride === null || propStatusesForOverride === void 0 ? void 0 : propStatusesForOverride.freeze;
324
+ const runtimeFreezeFrame = typeof ((_c = s.controls) === null || _c === void 0 ? void 0 : _c.currentRuntimeValueDotNotation.freeze) === 'number'
325
+ ? s.controls.currentRuntimeValueDotNotation.freeze
326
+ : null;
327
+ const frozenFrame = (freezeStatus === null || freezeStatus === void 0 ? void 0 : freezeStatus.status) === 'static'
328
+ ? typeof freezeStatus.codeValue === 'number'
329
+ ? freezeStatus.codeValue
330
+ : null
331
+ : runtimeFreezeFrame;
172
332
  const { onPointerDown: onMoveDragPointerDown } = (0, TimelineSequenceRightEdgeDragHandle_1.useTimelineSequenceFromDrag)({
173
333
  nodePathInfo,
174
334
  windowWidth,
175
- timelineDurationInFrames: (_e = video === null || video === void 0 ? void 0 : video.durationInFrames) !== null && _e !== void 0 ? _e : 1,
335
+ timelineDurationInFrames: (_f = video === null || video === void 0 ? void 0 : video.durationInFrames) !== null && _f !== void 0 ? _f : 1,
176
336
  });
177
337
  if (!video) {
178
338
  throw new TypeError('Expected video config');
@@ -226,6 +386,7 @@ const TimelineSequenceInner = ({ s, windowWidth, nodePathInfo, sequenceFrameOffs
226
386
  if (maxMediaDuration === null && !s.loopDisplay) {
227
387
  return null;
228
388
  }
229
- return (jsx_runtime_1.jsxs(TimelineSequenceCurrentFrame, { s: s, displayDurationInFrames: displayDurationInFrames, premountWidth: premountWidth, postmountWidth: postmountWidth, style: style, nodePathInfo: nodePathInfo, sequenceFrameOffset: sequenceFrameOffset, fromCanUpdate: fromCanUpdate, 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 })) : 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] }));
389
+ 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 })) : 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] }));
390
+ return previewConnected ? (jsx_runtime_1.jsx(ContextMenu_1.ContextMenu, { values: contextMenuValues, onOpen: onContextMenuOpen, children: sequence })) : (sequence);
230
391
  };
231
392
  exports.TimelineSequence = react_1.default.memo(TimelineSequenceFn);
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  export declare const TimelineSequenceFrame: React.FC<{
3
3
  readonly roundedFrame: number;
4
+ readonly frozenFrame: number | null;
4
5
  readonly premounted: boolean;
5
6
  readonly postmounted: number | null;
6
7
  }>;
@@ -3,19 +3,30 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TimelineSequenceFrame = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const relativeFrameStyle = {
6
+ alignItems: 'center',
7
+ display: 'flex',
6
8
  fontSize: 11,
7
9
  fontFamily: 'Arial, Helvetica, sans-serif',
10
+ gap: 4,
8
11
  color: 'white',
9
12
  opacity: 0.5,
10
13
  whiteSpace: 'nowrap',
11
14
  pointerEvents: 'none',
12
15
  userSelect: 'none',
13
16
  };
14
- const TimelineSequenceFrame = ({ roundedFrame, premounted, postmounted }) => {
15
- return (jsx_runtime_1.jsx("div", { style: relativeFrameStyle, children: premounted
16
- ? '0 (Premounted)'
17
- : postmounted !== null
18
- ? `${postmounted} (Postmounted)`
19
- : roundedFrame }));
17
+ const snowflakeStyle = {
18
+ flexShrink: 0,
19
+ height: 12,
20
+ width: 12,
21
+ };
22
+ const FreezeFrameIcon = () => {
23
+ return (jsx_runtime_1.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 512 512", style: snowflakeStyle, fill: "currentColor", children: jsx_runtime_1.jsx("path", { d: "M288 32l0-32-64 0 0 88.4-64-64-39.6 39.6 103.6 103.6 0 56.4-56.4 0-103.6-103.6-39.6 39.6 64 64-88.4 0 0 64 88.4 0c-33.5 33.5-54.9 54.9-64 64L64 391.6c2.5-2.5 37.1-37.1 103.6-103.6l56.4 0 0 56.4C157.5 410.9 122.9 445.5 120.4 448L160 487.6c9.1-9.1 30.5-30.5 64-64l0 88.4 64 0 0-88.4 64 64 39.6-39.6-103.6-103.6 0-56.4 56.4 0 103.6 103.6 39.6-39.6-64-64 88.4 0 0-64-88.4 0c33.5-33.5 54.9-54.9 64-64L448 120.4c-2.5 2.5-37.1 37.1-103.6 103.6l-56.4 0 0-56.4C354.5 101.1 389.1 66.5 391.6 64L352 24.4c-9.1 9.1-30.5 30.5-64 64L288 32z" }) }));
24
+ };
25
+ const TimelineSequenceFrame = ({ roundedFrame, frozenFrame, premounted, postmounted }) => {
26
+ return (jsx_runtime_1.jsxs("div", { style: relativeFrameStyle, children: [frozenFrame === null ? null : jsx_runtime_1.jsx(FreezeFrameIcon, {}), frozenFrame !== null && frozenFrame !== void 0 ? frozenFrame : (premounted
27
+ ? '0 (Premounted)'
28
+ : postmounted !== null
29
+ ? `${postmounted} (Postmounted)`
30
+ : roundedFrame)] }));
20
31
  };
21
32
  exports.TimelineSequenceFrame = TimelineSequenceFrame;
@@ -6,5 +6,6 @@ export declare const TimelineSequenceItem: React.FC<{
6
6
  readonly nestedDepth: number;
7
7
  readonly nodePathInfo: SequenceNodePathInfo | null;
8
8
  readonly keyframeDisplayOffset: number;
9
+ readonly sequenceFrameOffset: number;
9
10
  readonly trackIndex: number;
10
11
  }>;