@remotion/studio 4.0.493 → 4.0.495

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 (111) hide show
  1. package/dist/api/get-static-files.d.ts +1 -1
  2. package/dist/components/AssetFileIcon.d.ts +7 -0
  3. package/dist/components/AssetFileIcon.js +24 -0
  4. package/dist/components/AssetSelectorItem.js +13 -7
  5. package/dist/components/Canvas.js +194 -36
  6. package/dist/components/CompositionSelectorItem.js +15 -8
  7. package/dist/components/CurrentAsset.d.ts +1 -0
  8. package/dist/components/CurrentAsset.js +17 -1
  9. package/dist/components/Editor.js +2 -4
  10. package/dist/components/InitialCompositionLoader.d.ts +1 -1
  11. package/dist/components/InitialCompositionLoader.js +6 -1
  12. package/dist/components/InspectorPanel/AssetInspector.d.ts +4 -0
  13. package/dist/components/InspectorPanel/AssetInspector.js +11 -0
  14. package/dist/components/InspectorPanel/{DefaultInspector.d.ts → CompositionInspector.d.ts} +2 -2
  15. package/dist/components/InspectorPanel/CompositionInspector.js +114 -0
  16. package/dist/components/InspectorPanel/CompositionInspectorHeader.d.ts +1 -0
  17. package/dist/components/{CurrentComposition.js → InspectorPanel/CompositionInspectorHeader.js} +16 -16
  18. package/dist/components/InspectorPanel/{CompositionDimensions.d.ts → CompositionMetadata.d.ts} +1 -1
  19. package/dist/components/InspectorPanel/{CompositionDimensions.js → CompositionMetadata.js} +17 -8
  20. package/dist/components/InspectorPanel/ConnectedCompositionsSection.js +2 -2
  21. package/dist/components/InspectorPanel/EasingInspector.js +3 -5
  22. package/dist/components/InspectorPanel/KeyframeInspector.js +2 -2
  23. package/dist/components/InspectorPanel/SequenceSelectionInspector.js +34 -1
  24. package/dist/components/InspectorPanel/common.d.ts +8 -0
  25. package/dist/components/InspectorPanel/common.js +31 -8
  26. package/dist/components/InspectorPanel/styles.d.ts +5 -3
  27. package/dist/components/InspectorPanel/styles.js +13 -4
  28. package/dist/components/InspectorPanel/use-composition-actions.d.ts +8 -0
  29. package/dist/components/InspectorPanel/use-composition-actions.js +114 -0
  30. package/dist/components/InspectorPanel.js +11 -2
  31. package/dist/components/InspectorSequenceSection.d.ts +0 -1
  32. package/dist/components/InspectorSequenceSection.js +9 -48
  33. package/dist/components/Modals.js +2 -1
  34. package/dist/components/NewComposition/InputDragger.d.ts +6 -0
  35. package/dist/components/NewComposition/InputDragger.js +26 -13
  36. package/dist/components/NewComposition/NewComposition.js +8 -1
  37. package/dist/components/NewComposition/ValidationMessage.d.ts +1 -1
  38. package/dist/components/Preview.js +15 -7
  39. package/dist/components/RenderModal/RenderModalOutputName.js +34 -1
  40. package/dist/components/SelectedOutlineOverlay.js +1 -0
  41. package/dist/components/SvgImportDialog.d.ts +7 -0
  42. package/dist/components/SvgImportDialog.js +103 -0
  43. package/dist/components/Timeline/Timeline.js +2 -0
  44. package/dist/components/Timeline/TimelineClipboardKeybindings.js +11 -1
  45. package/dist/components/Timeline/TimelineDeleteKeybindings.js +2 -0
  46. package/dist/components/Timeline/TimelineKeyframeControls.js +1 -0
  47. package/dist/components/Timeline/TimelineList.js +9 -4
  48. package/dist/components/Timeline/TimelineSequence.d.ts +1 -0
  49. package/dist/components/Timeline/TimelineSequence.js +42 -6
  50. package/dist/components/Timeline/TimelineSequenceItem.d.ts +2 -1
  51. package/dist/components/Timeline/TimelineSequenceItem.js +33 -13
  52. package/dist/components/Timeline/TimelineTrack.js +2 -1
  53. package/dist/components/Timeline/call-delete-keyframe.d.ts +1 -0
  54. package/dist/components/Timeline/call-delete-keyframe.js +4 -0
  55. package/dist/components/Timeline/delete-selected-keyframe.d.ts +4 -2
  56. package/dist/components/Timeline/delete-selected-keyframe.js +48 -5
  57. package/dist/components/Timeline/delete-selected-timeline-item.d.ts +3 -1
  58. package/dist/components/Timeline/delete-selected-timeline-item.js +3 -1
  59. package/dist/components/Timeline/nest-timeline-tracks.d.ts +8 -0
  60. package/dist/components/Timeline/nest-timeline-tracks.js +25 -0
  61. package/dist/components/Timeline/timeline-scroll-logic.d.ts +8 -4
  62. package/dist/components/Timeline/timeline-scroll-logic.js +29 -15
  63. package/dist/components/import-assets.d.ts +41 -3
  64. package/dist/components/import-assets.js +148 -24
  65. package/dist/components/layout.d.ts +1 -0
  66. package/dist/components/layout.js +2 -1
  67. package/dist/components/selected-outline-measurement.d.ts +2 -1
  68. package/dist/components/selected-outline-measurement.js +3 -1
  69. package/dist/esm/{chunk-mndqr3zx.js → chunk-784jbkzs.js} +8604 -7249
  70. package/dist/esm/internals.mjs +8604 -7249
  71. package/dist/esm/previewEntry.mjs +8704 -7349
  72. package/dist/esm/renderEntry.mjs +1 -1
  73. package/dist/helpers/client-id.js +2 -1
  74. package/dist/helpers/clipboard-figma.d.ts +4 -0
  75. package/dist/helpers/clipboard-figma.js +41 -0
  76. package/dist/helpers/clipboard-images.d.ts +10 -0
  77. package/dist/helpers/clipboard-images.js +77 -0
  78. package/dist/helpers/clipboard-svg.d.ts +3 -0
  79. package/dist/helpers/clipboard-svg.js +47 -0
  80. package/dist/helpers/get-effective-translation.d.ts +2 -1
  81. package/dist/helpers/get-effective-translation.js +15 -7
  82. package/dist/helpers/get-preview-file-type.d.ts +1 -1
  83. package/dist/helpers/get-preview-file-type.js +5 -1
  84. package/dist/helpers/get-sequence-double-click-action.d.ts +6 -0
  85. package/dist/helpers/get-sequence-double-click-action.js +10 -1
  86. package/dist/helpers/inject-css.js +9 -2
  87. package/dist/helpers/studio-fit-padding.d.ts +41 -0
  88. package/dist/helpers/studio-fit-padding.js +64 -0
  89. package/dist/helpers/use-image-metadata.d.ts +8 -0
  90. package/dist/helpers/use-image-metadata.js +82 -0
  91. package/dist/helpers/use-studio-canvas-dimensions.js +2 -2
  92. package/dist/icons/audio.d.ts +3 -0
  93. package/dist/icons/audio.js +3 -1
  94. package/dist/icons/font.d.ts +4 -0
  95. package/dist/icons/font.js +8 -0
  96. package/dist/icons/frame.d.ts +3 -1
  97. package/dist/icons/frame.js +1 -1
  98. package/dist/icons/json.d.ts +4 -0
  99. package/dist/icons/json.js +8 -0
  100. package/dist/icons/magnet.js +1 -1
  101. package/dist/icons/scissors.d.ts +5 -0
  102. package/dist/icons/scissors.js +8 -0
  103. package/dist/icons/solid.d.ts +5 -0
  104. package/dist/icons/solid.js +8 -0
  105. package/dist/icons/video.d.ts +3 -0
  106. package/dist/icons/video.js +5 -1
  107. package/dist/state/modals.d.ts +8 -1
  108. package/dist/state/timeline-zoom.js +12 -11
  109. package/package.json +11 -11
  110. package/dist/components/CurrentComposition.d.ts +0 -2
  111. package/dist/components/InspectorPanel/DefaultInspector.js +0 -97
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SvgImportDialog = exports.useSvgImportDialog = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const modals_1 = require("../state/modals");
7
+ const Button_1 = require("./Button");
8
+ const layout_1 = require("./layout");
9
+ const ModalButton_1 = require("./ModalButton");
10
+ const ModalContainer_1 = require("./ModalContainer");
11
+ const ModalFooter_1 = require("./ModalFooter");
12
+ const ModalHeader_1 = require("./ModalHeader");
13
+ const content = {
14
+ padding: 16,
15
+ fontFamily: 'inherit',
16
+ fontSize: 14,
17
+ lineHeight: 1.4,
18
+ color: 'inherit',
19
+ minWidth: 560,
20
+ };
21
+ const inlineCode = {
22
+ fontFamily: 'monospace',
23
+ fontSize: 'inherit',
24
+ lineHeight: 'inherit',
25
+ color: 'inherit',
26
+ };
27
+ const useSvgImportDialog = () => {
28
+ const { setSelectedModal } = (0, react_1.useContext)(modals_1.ModalsContext);
29
+ return (0, react_1.useCallback)(() => {
30
+ return new Promise((resolve) => {
31
+ let settled = false;
32
+ const settle = (result) => {
33
+ if (settled) {
34
+ return;
35
+ }
36
+ settled = true;
37
+ resolve(result);
38
+ };
39
+ setSelectedModal({
40
+ type: 'svg-import-dialog',
41
+ id: String(Math.random()),
42
+ onImage: () => settle('image'),
43
+ onInline: () => settle('inline'),
44
+ onDismiss: () => settle(null),
45
+ });
46
+ });
47
+ }, [setSelectedModal]);
48
+ };
49
+ exports.useSvgImportDialog = useSvgImportDialog;
50
+ const SvgImportDialog = ({ state }) => {
51
+ const { setSelectedModal } = (0, react_1.useContext)(modals_1.ModalsContext);
52
+ const settledRef = (0, react_1.useRef)(false);
53
+ const closeCurrentModal = (0, react_1.useCallback)(() => {
54
+ setSelectedModal((modal) => (modal === null || modal === void 0 ? void 0 : modal.type) === 'svg-import-dialog' && modal.id === state.id
55
+ ? null
56
+ : modal);
57
+ }, [setSelectedModal, state.id]);
58
+ const settle = (0, react_1.useCallback)((result) => {
59
+ if (settledRef.current) {
60
+ return;
61
+ }
62
+ settledRef.current = true;
63
+ closeCurrentModal();
64
+ if (result === 'image') {
65
+ state.onImage();
66
+ }
67
+ else if (result === 'inline') {
68
+ state.onInline();
69
+ }
70
+ else {
71
+ state.onDismiss();
72
+ }
73
+ }, [closeCurrentModal, state]);
74
+ (0, react_1.useEffect)(() => {
75
+ return () => {
76
+ if (settledRef.current) {
77
+ return;
78
+ }
79
+ settledRef.current = true;
80
+ state.onDismiss();
81
+ };
82
+ }, [state]);
83
+ const onImage = (0, react_1.useCallback)(() => {
84
+ settle('image');
85
+ }, [settle]);
86
+ const onInline = (0, react_1.useCallback)(() => {
87
+ settle('inline');
88
+ }, [settle]);
89
+ const onDismiss = (0, react_1.useCallback)(() => {
90
+ settle(null);
91
+ }, [settle]);
92
+ return (jsx_runtime_1.jsxs(ModalContainer_1.ModalContainer, { onOutsideClick: onDismiss, onEscape: onDismiss, children: [
93
+ jsx_runtime_1.jsx(ModalHeader_1.ModalHeader, { title: "Add .svg", onClose: onDismiss }), jsx_runtime_1.jsx("div", { style: content, children: "Do you want to import this as an image or as inline SVG?" }), jsx_runtime_1.jsx(ModalFooter_1.ModalFooterContainer, { children: jsx_runtime_1.jsxs(layout_1.Row, { align: "center", children: [
94
+ jsx_runtime_1.jsx(layout_1.Flex, {}), jsx_runtime_1.jsxs(Button_1.Button, { onClick: onImage, children: ["Add to ",
95
+ jsx_runtime_1.jsx("code", { style: inlineCode, children: "public" }),
96
+ " and import as", ' ', jsx_runtime_1.jsx("code", { style: inlineCode, children: '<CanvasImage>' })
97
+ ] }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 1 }), jsx_runtime_1.jsxs(ModalButton_1.ModalButton, { onClick: onInline, autoFocus: true, children: ["Import as inline ",
98
+ jsx_runtime_1.jsx("code", { style: inlineCode, children: '<svg>' })
99
+ ] })
100
+ ] }) })
101
+ ] }));
102
+ };
103
+ exports.SvgImportDialog = SvgImportDialog;
@@ -164,7 +164,9 @@ const TimelineContextMenuArea = ({ children }) => {
164
164
  files,
165
165
  compositionFile,
166
166
  compositionId: currentCompositionId,
167
+ destinationDimensions: null,
167
168
  dropPosition: null,
169
+ svgImportMode: 'image',
168
170
  });
169
171
  }
170
172
  finally {
@@ -5,6 +5,9 @@ const studio_shared_1 = require("@remotion/studio-shared");
5
5
  const react_1 = require("react");
6
6
  const remotion_1 = require("remotion");
7
7
  const client_id_1 = require("../../helpers/client-id");
8
+ const clipboard_figma_1 = require("../../helpers/clipboard-figma");
9
+ const clipboard_images_1 = require("../../helpers/clipboard-images");
10
+ const clipboard_svg_1 = require("../../helpers/clipboard-svg");
8
11
  const use_keybinding_1 = require("../../helpers/use-keybinding");
9
12
  const call_api_1 = require("../call-api");
10
13
  const ConfirmationDialog_1 = require("../ConfirmationDialog");
@@ -532,6 +535,8 @@ const TimelineClipboardKeybindings = () => {
532
535
  setPropStatuses,
533
536
  clientId,
534
537
  confirm,
538
+ propStatuses,
539
+ timelinePosition: timelinePositionRef.current,
535
540
  });
536
541
  return deletePromise === null || deletePromise === void 0 ? void 0 : deletePromise.then((deleted) => {
537
542
  if (!deleted) {
@@ -565,7 +570,11 @@ const TimelineClipboardKeybindings = () => {
565
570
  return;
566
571
  }
567
572
  const { selectedItems } = currentSelection.current;
568
- if (selectedItems.length === 0 || e.clipboardData === null) {
573
+ if (selectedItems.length === 0 ||
574
+ e.clipboardData === null ||
575
+ (0, clipboard_figma_1.hasClipboardFigmaPayload)(e.clipboardData) ||
576
+ (0, clipboard_images_1.hasClipboardImage)(e.clipboardData) ||
577
+ (0, clipboard_svg_1.hasClipboardSvgMarkup)(e.clipboardData)) {
569
578
  return;
570
579
  }
571
580
  e.preventDefault();
@@ -621,6 +630,7 @@ const TimelineClipboardKeybindings = () => {
621
630
  fieldKey: keyframeTarget.fieldKey,
622
631
  sourceFrame,
623
632
  schema: keyframeTarget.schema,
633
+ valueWhenLastKeyframeDeleted: null,
624
634
  }));
625
635
  return (0, call_delete_keyframe_1.callDeleteKeyframes)({
626
636
  sequenceKeyframes: effectIndex === null ? deletions : [],
@@ -57,6 +57,8 @@ const TimelineDeleteKeybindings = () => {
57
57
  setPropStatuses,
58
58
  clientId,
59
59
  confirm,
60
+ propStatuses,
61
+ timelinePosition: timelinePositionRef.current,
60
62
  });
61
63
  if (deletePromise !== null) {
62
64
  deletePromise
@@ -213,6 +213,7 @@ const getDeleteChange = (target) => {
213
213
  fieldKey: target.fieldKey,
214
214
  sourceFrame: target.sourceFrame,
215
215
  schema: target.schema,
216
+ valueWhenLastKeyframeDeleted: null,
216
217
  };
217
218
  if (target.effectIndex === null) {
218
219
  return change;
@@ -2,18 +2,23 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TimelineList = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
5
6
  const colors_1 = require("../../helpers/colors");
7
+ const nest_timeline_tracks_1 = require("./nest-timeline-tracks");
6
8
  const TimelineSequenceItem_1 = require("./TimelineSequenceItem");
7
9
  const TimelineTimeIndicators_1 = require("./TimelineTimeIndicators");
8
10
  const container = {
9
11
  flex: 1,
10
12
  background: colors_1.BACKGROUND,
11
13
  };
14
+ const TimelineListTrack = ({ nestedTrack }) => {
15
+ var _a;
16
+ const { track, children, siblingIndex } = nestedTrack;
17
+ return (jsx_runtime_1.jsx("div", { children: jsx_runtime_1.jsx(TimelineSequenceItem_1.TimelineSequenceItem, { siblingIndex: siblingIndex, connectedCompositions: (_a = track.connectedCompositions) !== null && _a !== void 0 ? _a : [], nestedDepth: track.depth, sequence: track.sequence, nodePathInfo: track.nodePathInfo, keyframeDisplayOffset: track.keyframeDisplayOffset, sequenceFrameOffset: track.sequenceFrameOffset, children: children.map((child) => (jsx_runtime_1.jsx(TimelineListTrack, { nestedTrack: child }, child.track.sequence.id))) }) }));
18
+ };
12
19
  const TimelineList = ({ timeline }) => {
20
+ const nestedTimeline = (0, react_1.useMemo)(() => (0, nest_timeline_tracks_1.nestTimelineTracks)(timeline), [timeline]);
13
21
  return (jsx_runtime_1.jsxs("div", { style: container, children: [
14
- jsx_runtime_1.jsx(TimelineTimeIndicators_1.TimelineTimePadding, {}), timeline.map((track, trackIndex) => {
15
- var _a;
16
- return (jsx_runtime_1.jsx("div", { children: jsx_runtime_1.jsx(TimelineSequenceItem_1.TimelineSequenceItem, { trackIndex: trackIndex, connectedCompositions: (_a = track.connectedCompositions) !== null && _a !== void 0 ? _a : [], nestedDepth: track.depth, sequence: track.sequence, nodePathInfo: track.nodePathInfo, keyframeDisplayOffset: track.keyframeDisplayOffset, sequenceFrameOffset: track.sequenceFrameOffset }, track.sequence.id) }, track.sequence.id));
17
- })] }));
22
+ jsx_runtime_1.jsx(TimelineTimeIndicators_1.TimelineTimePadding, {}), nestedTimeline.map((nestedTrack) => (jsx_runtime_1.jsx(TimelineListTrack, { nestedTrack: nestedTrack }, nestedTrack.track.sequence.id)))] }));
18
23
  };
19
24
  exports.TimelineList = TimelineList;
@@ -3,6 +3,7 @@ import type { TSequence } from 'remotion';
3
3
  import type { SequenceNodePathInfo } from '../../helpers/get-timeline-sequence-sort-key';
4
4
  export declare const TimelineSequence: React.NamedExoticComponent<{
5
5
  readonly s: TSequence;
6
+ readonly connectedCompositions: readonly import("remotion").AnyComposition[];
6
7
  readonly nodePathInfo: SequenceNodePathInfo | null;
7
8
  readonly sequenceFrameOffset: number;
8
9
  }>;
@@ -40,6 +40,7 @@ const remotion_1 = require("remotion");
40
40
  const client_id_1 = require("../../helpers/client-id");
41
41
  const colors_1 = require("../../helpers/colors");
42
42
  const format_file_location_1 = require("../../helpers/format-file-location");
43
+ const get_sequence_double_click_action_1 = require("../../helpers/get-sequence-double-click-action");
43
44
  const get_timeline_sequence_layout_1 = require("../../helpers/get-timeline-sequence-layout");
44
45
  const interactivity_enabled_1 = require("../../helpers/interactivity-enabled");
45
46
  const open_in_editor_1 = require("../../helpers/open-in-editor");
@@ -49,6 +50,7 @@ const AudioWaveform_1 = require("../AudioWaveform");
49
50
  const call_api_1 = require("../call-api");
50
51
  const ConfirmationDialog_1 = require("../ConfirmationDialog");
51
52
  const ContextMenu_1 = require("../ContextMenu");
53
+ const InitialCompositionLoader_1 = require("../InitialCompositionLoader");
52
54
  const NotificationCenter_1 = require("../Notifications/NotificationCenter");
53
55
  const use_select_asset_1 = require("../use-select-asset");
54
56
  const disable_sequence_interactivity_1 = require("./disable-sequence-interactivity");
@@ -64,14 +66,14 @@ const TimelineVideoInfo_1 = require("./TimelineVideoInfo");
64
66
  const TimelineWidthProvider_1 = require("./TimelineWidthProvider");
65
67
  const use_resolved_stack_react_to_change_1 = require("./use-resolved-stack-react-to-change");
66
68
  const use_sequence_freeze_frame_menu_item_1 = require("./use-sequence-freeze-frame-menu-item");
67
- const TimelineSequenceFn = ({ s, nodePathInfo, sequenceFrameOffset }) => {
69
+ const TimelineSequenceFn = ({ s, connectedCompositions, nodePathInfo, sequenceFrameOffset }) => {
68
70
  const windowWidth = (0, react_1.useContext)(TimelineWidthProvider_1.TimelineWidthContext);
69
71
  if (windowWidth === null) {
70
72
  return null;
71
73
  }
72
- return (jsx_runtime_1.jsx(TimelineSequenceInner, { windowWidth: windowWidth, s: s, nodePathInfo: nodePathInfo, sequenceFrameOffset: sequenceFrameOffset }));
74
+ return (jsx_runtime_1.jsx(TimelineSequenceInner, { windowWidth: windowWidth, s: s, connectedCompositions: connectedCompositions, nodePathInfo: nodePathInfo, sequenceFrameOffset: sequenceFrameOffset }));
73
75
  };
74
- const TimelineSequenceCurrentFrame = ({ s, displayDurationInFrames, premountWidth, postmountWidth, style, children, nodePathInfo, sequenceFrameOffset, fromCanUpdate, frozenFrame, onMoveDragPointerDown, }) => {
76
+ const TimelineSequenceCurrentFrame = ({ s, displayDurationInFrames, premountWidth, postmountWidth, style, children, nodePathInfo, sequenceFrameOffset, fromCanUpdate, frozenFrame, onMoveDragPointerDown, onDoubleClick, }) => {
75
77
  var _a, _b;
76
78
  const ref = (0, react_1.useRef)(null);
77
79
  const { onSelect, selectable, selected, selectionItem } = (0, TimelineSelection_1.useTimelineRowSelection)(nodePathInfo);
@@ -114,7 +116,7 @@ const TimelineSequenceCurrentFrame = ({ s, displayDurationInFrames, premountWidt
114
116
  opacity: isInRange ? 1 : 0.5,
115
117
  };
116
118
  }, [isInRange, style]);
117
- return (jsx_runtime_1.jsxs("div", { ref: ref, [TimelineSelection_1.TIMELINE_MARQUEE_ITEM_ATTR]: true, style: actualStyle, title: s.displayName, onPointerDown: selectable ? onPointerDown : undefined, children: [premountWidth ? (jsx_runtime_1.jsx("div", { style: {
119
+ return (jsx_runtime_1.jsxs("div", { ref: ref, [TimelineSelection_1.TIMELINE_MARQUEE_ITEM_ATTR]: true, style: actualStyle, title: s.displayName, onPointerDown: selectable ? onPointerDown : undefined, onDoubleClick: onDoubleClick, children: [premountWidth ? (jsx_runtime_1.jsx("div", { style: {
118
120
  width: premountWidth,
119
121
  height: '100%',
120
122
  background: `repeating-linear-gradient(
@@ -148,7 +150,7 @@ const TimelineSequenceCurrentFrame = ({ s, displayDurationInFrames, premountWidt
148
150
  alignItems: 'center',
149
151
  }, children: jsx_runtime_1.jsx(TimelineSequenceFrame_1.TimelineSequenceFrame, { premounted: isPremounting, postmounted: isPostmounting ? s.duration - 1 : null, roundedFrame: roundedFrame, frozenFrame: frozenFrame }) })) : null] }));
150
152
  };
151
- const TimelineSequenceInner = ({ s, windowWidth, nodePathInfo, sequenceFrameOffset }) => {
153
+ const TimelineSequenceInner = ({ s, connectedCompositions, windowWidth, nodePathInfo, sequenceFrameOffset, }) => {
152
154
  // If a duration is 1, it is essentially a still and it should have width 0
153
155
  // Some compositions may not be longer than their media duration,
154
156
  // if that is the case, it needs to be asynchronously determined
@@ -190,6 +192,7 @@ const TimelineSequenceInner = ({ s, windowWidth, nodePathInfo, sequenceFrameOffs
190
192
  const { setPropStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
191
193
  const timelinePosition = remotion_1.Internals.Timeline.useTimelinePosition();
192
194
  const selectAsset = (0, use_select_asset_1.useSelectAsset)();
195
+ const selectComposition = (0, InitialCompositionLoader_1.useSelectComposition)();
193
196
  const confirm = (0, ConfirmationDialog_1.useConfirmationDialog)();
194
197
  const { onSelect, selectable } = (0, TimelineSelection_1.useTimelineRowSelection)(nodePathInfo);
195
198
  const fileLocation = (0, react_1.useMemo)(() => (0, format_file_location_1.formatFileLocation)({
@@ -205,6 +208,39 @@ const TimelineSequenceInner = ({ s, windowWidth, nodePathInfo, sequenceFrameOffs
205
208
  (0, NotificationCenter_1.showNotification)(err.message, 2000);
206
209
  });
207
210
  }, [canOpenInEditor, originalLocation]);
211
+ const onSequenceDoubleClick = (0, react_1.useCallback)((e) => {
212
+ if ((0, TimelineSelection_1.isTimelineSelectionModifierEvent)(e)) {
213
+ e.stopPropagation();
214
+ return;
215
+ }
216
+ const action = (0, get_sequence_double_click_action_1.getSequenceDoubleClickAction)({
217
+ button: e.button,
218
+ canOpenInEditor,
219
+ numberOfConnectedCompositions: connectedCompositions.length,
220
+ });
221
+ if (action === null) {
222
+ return;
223
+ }
224
+ e.stopPropagation();
225
+ if (action === 'open-connected-composition') {
226
+ selectComposition(connectedCompositions[0], true, (0, get_sequence_double_click_action_1.getConnectedCompositionFrame)({
227
+ timelinePosition,
228
+ sequence: s,
229
+ sequenceFrameOffset,
230
+ }));
231
+ return;
232
+ }
233
+ openInEditor();
234
+ }, [
235
+ canOpenInEditor,
236
+ connectedCompositions,
237
+ openInEditor,
238
+ s,
239
+ selectComposition,
240
+ sequenceFrameOffset,
241
+ timelinePosition,
242
+ ]);
243
+ const canHandleSequenceDoubleClick = connectedCompositions.length === 1 || canOpenInEditor;
208
244
  const canDeleteFromSource = Boolean(nodePath && (validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source));
209
245
  const deleteDisabled = !previewInteractive || !s.controls || !canDeleteFromSource;
210
246
  const duplicateDisabled = deleteDisabled;
@@ -408,7 +444,7 @@ const TimelineSequenceInner = ({ s, windowWidth, nodePathInfo, sequenceFrameOffs
408
444
  if (maxMediaDuration === null && !s.loopDisplay) {
409
445
  return null;
410
446
  }
411
- 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, startMediaFrom: s.startMediaFrom, mediaFrameAtSequenceZero: s.mediaFrameAtSequenceZero, sequenceFrameOffset: sequenceFrameOffset, 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 })), showLeftEdgeDragHandle && nodePathInfo && validatedLocation ? (jsx_runtime_1.jsx(TimelineSequenceRightEdgeDragHandle_1.TimelineSequenceLeftEdgeDragHandle, { nodePathInfo: nodePathInfo, windowWidth: windowWidth, timelineDurationInFrames: (_h = video.durationInFrames) !== null && _h !== void 0 ? _h : 1 })) : null, showRightEdgeDragHandle && nodePathInfo && validatedLocation ? (jsx_runtime_1.jsx(TimelineSequenceRightEdgeDragHandle_1.TimelineSequenceRightEdgeDragHandle, { nodePathInfo: nodePathInfo, windowWidth: windowWidth, timelineDurationInFrames: (_j = video.durationInFrames) !== null && _j !== void 0 ? _j : 1 })) : null] }));
447
+ 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, onDoubleClick: canHandleSequenceDoubleClick ? onSequenceDoubleClick : undefined, 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, startMediaFrom: s.startMediaFrom, mediaFrameAtSequenceZero: s.mediaFrameAtSequenceZero, sequenceFrameOffset: sequenceFrameOffset, 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 })), showLeftEdgeDragHandle && nodePathInfo && validatedLocation ? (jsx_runtime_1.jsx(TimelineSequenceRightEdgeDragHandle_1.TimelineSequenceLeftEdgeDragHandle, { nodePathInfo: nodePathInfo, windowWidth: windowWidth, timelineDurationInFrames: (_h = video.durationInFrames) !== null && _h !== void 0 ? _h : 1 })) : null, showRightEdgeDragHandle && nodePathInfo && validatedLocation ? (jsx_runtime_1.jsx(TimelineSequenceRightEdgeDragHandle_1.TimelineSequenceRightEdgeDragHandle, { nodePathInfo: nodePathInfo, windowWidth: windowWidth, timelineDurationInFrames: (_j = video.durationInFrames) !== null && _j !== void 0 ? _j : 1 })) : null] }));
412
448
  return previewConnected ? (jsx_runtime_1.jsx(ContextMenu_1.ContextMenu, { values: contextMenuValues, onOpen: onContextMenuOpen, children: sequence })) : (sequence);
413
449
  };
414
450
  exports.TimelineSequence = react_1.default.memo(TimelineSequenceFn);
@@ -2,11 +2,12 @@ import React from 'react';
2
2
  import type { _InternalTypes, TSequence } from 'remotion';
3
3
  import type { SequenceNodePathInfo } from '../../helpers/get-timeline-sequence-sort-key';
4
4
  export declare const TimelineSequenceItem: React.FC<{
5
+ readonly children: React.ReactNode;
5
6
  readonly sequence: TSequence;
6
7
  readonly connectedCompositions: readonly _InternalTypes['AnyComposition'][];
7
8
  readonly nestedDepth: number;
8
9
  readonly nodePathInfo: SequenceNodePathInfo | null;
9
10
  readonly keyframeDisplayOffset: number;
10
11
  readonly sequenceFrameOffset: number;
11
- readonly trackIndex: number;
12
+ readonly siblingIndex: number;
12
13
  }>;
@@ -115,6 +115,14 @@ const sequenceReorderLineBase = {
115
115
  right: 0,
116
116
  zIndex: 1,
117
117
  };
118
+ const sequenceReorderAfterLineWrapper = {
119
+ height: 0,
120
+ position: 'relative',
121
+ };
122
+ const sequenceReorderAfterLine = {
123
+ ...sequenceReorderLineBase,
124
+ top: -1,
125
+ };
118
126
  const sequenceReorderRejectionStyle = {
119
127
  backgroundColor: colors_1.BLACK_ALPHA_85,
120
128
  border: colors_1.BORDER_WHITE_ALPHA_20,
@@ -147,7 +155,7 @@ const getSequenceReorderDragData = (dataTransfer) => {
147
155
  try {
148
156
  const parsed = JSON.parse(value);
149
157
  if (typeof parsed.nodePathKey === 'string' &&
150
- typeof parsed.trackIndex === 'number' &&
158
+ typeof parsed.siblingIndex === 'number' &&
151
159
  (typeof parsed.parentId === 'string' || parsed.parentId === null) &&
152
160
  typeof parsed.fileName === 'string' &&
153
161
  parsed.nodePath &&
@@ -163,7 +171,7 @@ const getSequenceReorderDragData = (dataTransfer) => {
163
171
  const getDestinationIndex = ({ fromIndex, insertionIndex, }) => {
164
172
  return insertionIndex > fromIndex ? insertionIndex - 1 : insertionIndex;
165
173
  };
166
- const TimelineSequenceItem = ({ connectedCompositions, nestedDepth, sequence, nodePathInfo, keyframeDisplayOffset, sequenceFrameOffset, trackIndex, }) => {
174
+ const TimelineSequenceItem = ({ children, connectedCompositions, nestedDepth, sequence, nodePathInfo, keyframeDisplayOffset, sequenceFrameOffset, siblingIndex, }) => {
167
175
  var _a, _b, _c;
168
176
  var _d, _e, _f;
169
177
  const nodePath = (_d = nodePathInfo === null || nodePathInfo === void 0 ? void 0 : nodePathInfo.sequenceSubscriptionKey) !== null && _d !== void 0 ? _d : null;
@@ -328,12 +336,12 @@ const TimelineSequenceItem = ({ connectedCompositions, nestedDepth, sequence, no
328
336
  }
329
337
  const rect = e.currentTarget.getBoundingClientRect();
330
338
  const before = e.clientY < rect.top + rect.height / 2;
331
- const insertionIndex = before ? trackIndex : trackIndex + 1;
339
+ const insertionIndex = before ? siblingIndex : siblingIndex + 1;
332
340
  const toIndex = getDestinationIndex({
333
- fromIndex: dragData.trackIndex,
341
+ fromIndex: dragData.siblingIndex,
334
342
  insertionIndex,
335
343
  });
336
- if (toIndex === dragData.trackIndex) {
344
+ if (toIndex === dragData.siblingIndex) {
337
345
  return {
338
346
  type: 'invalid',
339
347
  reason: 'This sequence is already in that position.',
@@ -349,7 +357,7 @@ const TimelineSequenceItem = ({ connectedCompositions, nestedDepth, sequence, no
349
357
  nodePathInfo === null || nodePathInfo === void 0 ? void 0 : nodePathInfo.numberOfSequencesWithThisNodePath,
350
358
  nodePathKey,
351
359
  parentId,
352
- trackIndex,
360
+ siblingIndex,
353
361
  validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source,
354
362
  ]);
355
363
  const onSequenceDragStart = (0, react_1.useCallback)((e) => {
@@ -363,7 +371,7 @@ const TimelineSequenceItem = ({ connectedCompositions, nestedDepth, sequence, no
363
371
  const dragData = {
364
372
  nodePath,
365
373
  nodePathKey,
366
- trackIndex,
374
+ siblingIndex,
367
375
  parentId,
368
376
  fileName: validatedLocation.source,
369
377
  };
@@ -376,7 +384,7 @@ const TimelineSequenceItem = ({ connectedCompositions, nestedDepth, sequence, no
376
384
  nodePath,
377
385
  nodePathKey,
378
386
  parentId,
379
- trackIndex,
387
+ siblingIndex,
380
388
  validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source,
381
389
  ]);
382
390
  const onSequenceDragEnd = (0, react_1.useCallback)(() => {
@@ -563,11 +571,23 @@ const TimelineSequenceItem = ({ connectedCompositions, nestedDepth, sequence, no
563
571
  }
564
572
  e.stopPropagation();
565
573
  if (action === 'open-connected-composition') {
566
- selectComposition(connectedCompositions[0], true);
574
+ selectComposition(connectedCompositions[0], true, (0, get_sequence_double_click_action_1.getConnectedCompositionFrame)({
575
+ timelinePosition,
576
+ sequence,
577
+ sequenceFrameOffset,
578
+ }));
567
579
  return;
568
580
  }
569
581
  openInEditor();
570
- }, [canOpenInEditor, connectedCompositions, openInEditor, selectComposition]);
582
+ }, [
583
+ canOpenInEditor,
584
+ connectedCompositions,
585
+ openInEditor,
586
+ selectComposition,
587
+ sequence,
588
+ sequenceFrameOffset,
589
+ timelinePosition,
590
+ ]);
571
591
  const canHandleSequenceDoubleClick = connectedCompositions.length === 1 || canOpenInEditor;
572
592
  const canRenameSelectedSequence = canRenameThisSequence &&
573
593
  selected &&
@@ -735,12 +755,12 @@ const TimelineSequenceItem = ({ connectedCompositions, nestedDepth, sequence, no
735
755
  validatedLocation !== null &&
736
756
  ((_c = sequence.controls) === null || _c === void 0 ? void 0 : _c.supportsEffects) === true;
737
757
  const sequenceReorderLineStyle = (0, react_1.useMemo)(() => {
738
- if (!sequenceDropIndicator) {
758
+ if (sequenceDropIndicator !== 'before') {
739
759
  return null;
740
760
  }
741
761
  return {
742
762
  ...sequenceReorderLineBase,
743
- ...(sequenceDropIndicator === 'before' ? { top: -1 } : { bottom: -1 }),
763
+ top: -1,
744
764
  };
745
765
  }, [sequenceDropIndicator]);
746
766
  const onEffectDragOver = (0, react_1.useCallback)((e) => {
@@ -801,6 +821,6 @@ const TimelineSequenceItem = ({ connectedCompositions, nestedDepth, sequence, no
801
821
  isExpanded &&
802
822
  hasExpandableContent &&
803
823
  nodePathInfo &&
804
- validatedLocation ? (jsx_runtime_1.jsx(TimelineExpandedSection_1.TimelineExpandedSection, { sequence: sequence, validatedLocation: validatedLocation, nodePathInfo: nodePathInfo, nestedDepth: nestedDepth, keyframeDisplayOffset: keyframeDisplayOffset })) : null] }));
824
+ validatedLocation ? (jsx_runtime_1.jsx(TimelineExpandedSection_1.TimelineExpandedSection, { sequence: sequence, validatedLocation: validatedLocation, nodePathInfo: nodePathInfo, nestedDepth: nestedDepth, keyframeDisplayOffset: keyframeDisplayOffset })) : null, children, sequenceDropIndicator === 'after' ? (jsx_runtime_1.jsx("div", { style: sequenceReorderAfterLineWrapper, children: jsx_runtime_1.jsx("div", { style: sequenceReorderAfterLine }) })) : null] }));
805
825
  };
806
826
  exports.TimelineSequenceItem = TimelineSequenceItem;
@@ -44,6 +44,7 @@ const TimelineSelection_1 = require("./TimelineSelection");
44
44
  const TimelineSequence_1 = require("./TimelineSequence");
45
45
  const TimelineWidthProvider_1 = require("./TimelineWidthProvider");
46
46
  const TimelineTrackUnmemoized = ({ track }) => {
47
+ var _a;
47
48
  const { getIsExpanded } = (0, react_1.useContext)(ExpandedTracksProvider_1.ExpandedTracksGetterContext);
48
49
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
49
50
  const previewServerConnected = previewServerState.type === 'connected';
@@ -58,7 +59,7 @@ const TimelineTrackUnmemoized = ({ track }) => {
58
59
  previewServerConnected &&
59
60
  getIsExpanded(track.nodePathInfo);
60
61
  return (jsx_runtime_1.jsxs("div", { children: [
61
- jsx_runtime_1.jsxs("div", { style: layerStyle, children: [rowHighlightBackground && timelineWidth !== null ? (jsx_runtime_1.jsx("div", { style: (0, TimelineSelection_1.getTimelineSelectedTrackHighlightStyle)(timelineWidth, rowHighlightBackground) })) : null, jsx_runtime_1.jsx(TimelineSequence_1.TimelineSequence, { s: track.sequence, nodePathInfo: track.nodePathInfo, sequenceFrameOffset: track.sequenceFrameOffset })
62
+ jsx_runtime_1.jsxs("div", { style: layerStyle, children: [rowHighlightBackground && timelineWidth !== null ? (jsx_runtime_1.jsx("div", { style: (0, TimelineSelection_1.getTimelineSelectedTrackHighlightStyle)(timelineWidth, rowHighlightBackground) })) : null, jsx_runtime_1.jsx(TimelineSequence_1.TimelineSequence, { s: track.sequence, connectedCompositions: (_a = track.connectedCompositions) !== null && _a !== void 0 ? _a : [], nodePathInfo: track.nodePathInfo, sequenceFrameOffset: track.sequenceFrameOffset })
62
63
  ] }), showExpandedKeyframes && track.nodePathInfo ? (jsx_runtime_1.jsx(TimelineExpandedTrackKeyframes_1.TimelineExpandedTrackKeyframes, { sequence: track.sequence, nodePathInfo: track.nodePathInfo, keyframeDisplayOffset: track.keyframeDisplayOffset })) : null] }));
63
64
  };
64
65
  exports.TimelineTrack = react_1.default.memo(TimelineTrackUnmemoized);
@@ -6,6 +6,7 @@ export type DeleteSequenceKeyframeChange = {
6
6
  fieldKey: string;
7
7
  sourceFrame: number;
8
8
  schema: InteractivitySchema;
9
+ valueWhenLastKeyframeDeleted: unknown | null;
9
10
  };
10
11
  export type DeleteEffectKeyframeChange = DeleteSequenceKeyframeChange & {
11
12
  effectIndex: number;
@@ -83,6 +83,7 @@ const callDeleteKeyframes = ({ sequenceKeyframes, effectKeyframes, setPropStatus
83
83
  keyframes: keyframes.map((keyframe) => ({
84
84
  fieldKey: keyframe.fieldKey,
85
85
  frame: keyframe.sourceFrame,
86
+ valueWhenLastKeyframeDeleted: keyframe.valueWhenLastKeyframeDeleted,
86
87
  })),
87
88
  }));
88
89
  }
@@ -97,6 +98,7 @@ const callDeleteKeyframes = ({ sequenceKeyframes, effectKeyframes, setPropStatus
97
98
  effectIndex: keyframe.effectIndex,
98
99
  fieldKey: keyframe.fieldKey,
99
100
  frame: keyframe.sourceFrame,
101
+ valueWhenLastKeyframeDeleted: keyframe.valueWhenLastKeyframeDeleted,
100
102
  })),
101
103
  }));
102
104
  }
@@ -107,6 +109,7 @@ const callDeleteKeyframes = ({ sequenceKeyframes, effectKeyframes, setPropStatus
107
109
  key: keyframe.fieldKey,
108
110
  frame: keyframe.sourceFrame,
109
111
  schema: keyframe.schema,
112
+ valueWhenLastKeyframeDeleted: keyframe.valueWhenLastKeyframeDeleted,
110
113
  })),
111
114
  effectKeyframes: effectKeyframes.map((keyframe) => ({
112
115
  fileName: keyframe.fileName,
@@ -115,6 +118,7 @@ const callDeleteKeyframes = ({ sequenceKeyframes, effectKeyframes, setPropStatus
115
118
  key: keyframe.fieldKey,
116
119
  frame: keyframe.sourceFrame,
117
120
  schema: keyframe.schema,
121
+ valueWhenLastKeyframeDeleted: keyframe.valueWhenLastKeyframeDeleted,
118
122
  })),
119
123
  clientId,
120
124
  }).then(() => undefined);
@@ -1,4 +1,4 @@
1
- import type { OverrideIdToNodePaths, TSequence } from 'remotion';
1
+ import type { OverrideIdToNodePaths, PropStatuses, TSequence } from 'remotion';
2
2
  import type { SequenceNodePathInfo } from '../../helpers/get-timeline-sequence-sort-key';
3
3
  import type { SetPropStatuses } from './save-sequence-prop';
4
4
  export declare const deleteSelectedKeyframe: ({ nodePathInfo, frame, sequences, overrideIdsToNodePaths, setPropStatuses, clientId, }: {
@@ -9,7 +9,7 @@ export declare const deleteSelectedKeyframe: ({ nodePathInfo, frame, sequences,
9
9
  setPropStatuses: SetPropStatuses;
10
10
  clientId: string;
11
11
  }) => Promise<void> | null;
12
- export declare const deleteSelectedKeyframes: ({ keyframes, sequences, overrideIdsToNodePaths, setPropStatuses, clientId, }: {
12
+ export declare const deleteSelectedKeyframes: ({ keyframes, sequences, overrideIdsToNodePaths, setPropStatuses, clientId, propStatuses, timelinePosition, }: {
13
13
  keyframes: {
14
14
  nodePathInfo: SequenceNodePathInfo;
15
15
  frame: number;
@@ -18,4 +18,6 @@ export declare const deleteSelectedKeyframes: ({ keyframes, sequences, overrideI
18
18
  overrideIdsToNodePaths: OverrideIdToNodePaths;
19
19
  setPropStatuses: SetPropStatuses;
20
20
  clientId: string;
21
+ propStatuses: PropStatuses;
22
+ timelinePosition: number;
21
23
  }) => Promise<void> | null;