@remotion/studio 4.0.469 → 4.0.470

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 (90) hide show
  1. package/dist/Studio.js +1 -1
  2. package/dist/api/save-render-output.js +3 -12
  3. package/dist/components/AudioWaveform.js +19 -2
  4. package/dist/components/ContextMenu.js +5 -1
  5. package/dist/components/EditorContent.js +5 -4
  6. package/dist/components/Menu/MenuItem.d.ts +1 -1
  7. package/dist/components/MenuBuildIndicator.js +0 -1
  8. package/dist/components/NewComposition/InputDragger.js +1 -0
  9. package/dist/components/Preview.js +4 -1
  10. package/dist/components/SelectedOutlineOverlay.d.ts +18 -0
  11. package/dist/components/SelectedOutlineOverlay.js +645 -0
  12. package/dist/components/Timeline/Timeline.js +27 -13
  13. package/dist/components/Timeline/TimelineDeleteKeybindings.d.ts +2 -0
  14. package/dist/components/Timeline/TimelineDeleteKeybindings.js +86 -0
  15. package/dist/components/Timeline/TimelineDragHandler.js +19 -244
  16. package/dist/components/Timeline/{TimelineEffectGroupRow.d.ts → TimelineEffectItem.d.ts} +1 -1
  17. package/dist/components/Timeline/{TimelineEffectGroupRow.js → TimelineEffectItem.js} +50 -33
  18. package/dist/components/Timeline/{TimelineEffectFieldRow.d.ts → TimelineEffectPropItem.d.ts} +2 -1
  19. package/dist/components/Timeline/{TimelineEffectFieldRow.js → TimelineEffectPropItem.js} +97 -8
  20. package/dist/components/Timeline/TimelineExpandArrowButton.js +5 -1
  21. package/dist/components/Timeline/TimelineExpandedKeyframeRow.js +37 -5
  22. package/dist/components/Timeline/TimelineExpandedRow.d.ts +1 -0
  23. package/dist/components/Timeline/TimelineExpandedRow.js +9 -7
  24. package/dist/components/Timeline/TimelineExpandedSection.d.ts +1 -0
  25. package/dist/components/Timeline/TimelineExpandedSection.js +2 -2
  26. package/dist/components/Timeline/TimelineInOutDragHandler.d.ts +2 -0
  27. package/dist/components/Timeline/TimelineInOutDragHandler.js +324 -0
  28. package/dist/components/Timeline/TimelineInOutPointer.js +3 -1
  29. package/dist/components/Timeline/TimelineInOutPointerHandle.d.ts +1 -0
  30. package/dist/components/Timeline/TimelineInOutPointerHandle.js +5 -4
  31. package/dist/components/Timeline/TimelineKeyframeControls.d.ts +17 -0
  32. package/dist/components/Timeline/TimelineKeyframeControls.js +217 -0
  33. package/dist/components/Timeline/TimelineKeyframeDiamond.js +7 -6
  34. package/dist/components/Timeline/TimelineKeyframedValue.d.ts +8 -0
  35. package/dist/components/Timeline/TimelineKeyframedValue.js +36 -0
  36. package/dist/components/Timeline/TimelineList.js +3 -15
  37. package/dist/components/Timeline/TimelineRowChrome.d.ts +3 -1
  38. package/dist/components/Timeline/TimelineRowChrome.js +23 -5
  39. package/dist/components/Timeline/TimelineSelection.d.ts +53 -9
  40. package/dist/components/Timeline/TimelineSelection.js +305 -48
  41. package/dist/components/Timeline/TimelineSequence.d.ts +2 -0
  42. package/dist/components/Timeline/TimelineSequence.js +18 -6
  43. package/dist/components/Timeline/TimelineSequenceFrame.js +1 -0
  44. package/dist/components/Timeline/{TimelineListItem.d.ts → TimelineSequenceItem.d.ts} +2 -1
  45. package/dist/components/Timeline/{TimelineListItem.js → TimelineSequenceItem.js} +49 -33
  46. package/dist/components/Timeline/{TimelineFieldRow.d.ts → TimelineSequencePropItem.d.ts} +2 -1
  47. package/dist/components/Timeline/{TimelineFieldRow.js → TimelineSequencePropItem.js} +81 -5
  48. package/dist/components/Timeline/TimelineTimeIndicators.js +0 -1
  49. package/dist/components/Timeline/TimelineTrack.js +3 -1
  50. package/dist/components/Timeline/TimelineTranslateField.js +14 -22
  51. package/dist/components/Timeline/call-add-keyframe.d.ts +23 -0
  52. package/dist/components/Timeline/call-add-keyframe.js +54 -0
  53. package/dist/components/Timeline/call-delete-keyframe.d.ts +21 -0
  54. package/dist/components/Timeline/call-delete-keyframe.js +50 -0
  55. package/dist/components/Timeline/delete-selected-keyframe.d.ts +11 -0
  56. package/dist/components/Timeline/delete-selected-keyframe.js +51 -0
  57. package/dist/components/Timeline/delete-selected-timeline-item.d.ts +17 -0
  58. package/dist/components/Timeline/delete-selected-timeline-item.js +183 -0
  59. package/dist/components/Timeline/duplicate-selected-timeline-item.d.ts +13 -0
  60. package/dist/components/Timeline/duplicate-selected-timeline-item.js +66 -0
  61. package/dist/components/Timeline/find-track-for-node-path-info.d.ts +7 -0
  62. package/dist/components/Timeline/find-track-for-node-path-info.js +13 -0
  63. package/dist/components/Timeline/get-keyframe-navigation.d.ts +9 -0
  64. package/dist/components/Timeline/get-keyframe-navigation.js +26 -0
  65. package/dist/components/Timeline/parse-keyframe-field-from-node-path.d.ts +8 -0
  66. package/dist/components/Timeline/parse-keyframe-field-from-node-path.js +26 -0
  67. package/dist/components/Timeline/save-sequence-prop.d.ts +14 -2
  68. package/dist/components/Timeline/save-sequence-prop.js +42 -7
  69. package/dist/components/Timeline/timeline-row-layout.d.ts +1 -0
  70. package/dist/components/Timeline/timeline-row-layout.js +2 -1
  71. package/dist/components/Timeline/timeline-translate-utils.d.ts +2 -0
  72. package/dist/components/Timeline/timeline-translate-utils.js +20 -0
  73. package/dist/components/Timeline/use-expanded-track-keyframe-rows.js +10 -3
  74. package/dist/components/composition-menu-items.js +32 -1
  75. package/dist/error-overlay/remotion-overlay/OpenInEditor.js +0 -1
  76. package/dist/esm/{chunk-1mp51e0w.js → chunk-dny42qnq.js} +9896 -6174
  77. package/dist/esm/internals.mjs +9896 -6174
  78. package/dist/esm/previewEntry.mjs +9870 -6148
  79. package/dist/esm/renderEntry.mjs +3 -1
  80. package/dist/helpers/format-file-location.d.ts +9 -0
  81. package/dist/helpers/format-file-location.js +27 -0
  82. package/dist/helpers/get-box-quads-polyfill-internals.d.ts +82 -0
  83. package/dist/helpers/get-box-quads-polyfill-internals.js +2395 -0
  84. package/dist/helpers/get-box-quads-ponyfill.d.ts +10 -0
  85. package/dist/helpers/get-box-quads-ponyfill.js +23 -0
  86. package/dist/helpers/open-in-editor.d.ts +1 -1
  87. package/dist/helpers/open-in-editor.js +11 -26
  88. package/dist/helpers/use-menu-structure.js +8 -16
  89. package/dist/renderEntry.js +2 -2
  90. package/package.json +10 -10
@@ -52,6 +52,7 @@ const SubscribeToNodePaths_1 = require("./SubscribeToNodePaths");
52
52
  const timeline_refs_1 = require("./timeline-refs");
53
53
  const TimelineDragHandler_1 = require("./TimelineDragHandler");
54
54
  const TimelineHeightContainer_1 = require("./TimelineHeightContainer");
55
+ const TimelineInOutDragHandler_1 = require("./TimelineInOutDragHandler");
55
56
  const TimelineInOutPointer_1 = require("./TimelineInOutPointer");
56
57
  const TimelineList_1 = require("./TimelineList");
57
58
  const TimelinePinchZoom_1 = require("./TimelinePinchZoom");
@@ -71,6 +72,19 @@ const container = {
71
72
  backgroundColor: colors_1.BACKGROUND,
72
73
  };
73
74
  const noop = () => undefined;
75
+ const TimelineClearSelectionArea = ({ children }) => {
76
+ const { clearSelection } = (0, TimelineSelection_1.useTimelineSelection)();
77
+ // Selection-triggering click handlers in children call e.stopPropagation(),
78
+ // so any pointerdown that bubbles up here is by definition on empty space
79
+ // and should clear the current selection.
80
+ const onPointerDown = (0, react_1.useCallback)((e) => {
81
+ if (e.button !== 0) {
82
+ return;
83
+ }
84
+ clearSelection();
85
+ }, [clearSelection]);
86
+ return (jsx_runtime_1.jsx("div", { ref: timeline_refs_1.timelineVerticalScroll, style: container, className: 'css-reset ' + is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, onPointerDown: onPointerDown, children: children }));
87
+ };
74
88
  const TimelineInner = () => {
75
89
  var _a;
76
90
  const { sequences } = (0, react_1.useContext)(remotion_1.Internals.SequenceManager);
@@ -99,18 +113,18 @@ const TimelineInner = () => {
99
113
  : filtered;
100
114
  }, [filtered]);
101
115
  const hasBeenCut = filtered.length > shown.length;
102
- return (jsx_runtime_1.jsx("div", { ref: timeline_refs_1.timelineVerticalScroll, style: container, className: 'css-reset ' + is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: jsx_runtime_1.jsxs(TimelineSelection_1.TimelineSelectionProvider, { children: [sequences.map((sequence) => {
103
- if (!sequence.controls || !previewConnected || !sequence.getStack()) {
104
- return null;
105
- }
106
- return (jsx_runtime_1.jsx(SubscribeToNodePaths_1.SubscribeToNodePaths, { overrideId: sequence.controls.overrideId, schema: sequence.controls.schema, getStack: sequence.getStack, effects: sequence.effects }, sequence.id));
107
- }), jsx_runtime_1.jsx(SequencePropsObserver_1.SequencePropsObserver, {}), jsx_runtime_1.jsx(TimelineHeightContainer_1.TimelineHeightContainer, { shown: shown, hasBeenCut: hasBeenCut, children: isStill ? (jsx_runtime_1.jsx(TimelineList_1.TimelineList, { timeline: shown })) : (jsx_runtime_1.jsxs(TimelineWidthProvider_1.TimelineWidthProvider, { children: [
108
- jsx_runtime_1.jsx(TimelinePinchZoom_1.TimelinePinchZoom, {}), jsx_runtime_1.jsxs(SplitterContainer_1.SplitterContainer, { orientation: "vertical", defaultFlex: 0.2, id: "names-to-timeline", maxFlex: 0.5, minFlex: 0.15, children: [
109
- jsx_runtime_1.jsx(SplitterElement_1.SplitterElement, { type: "flexer", sticky: jsx_runtime_1.jsx(TimelineTimeIndicators_1.TimelineTimePlaceholders, {}), children: jsx_runtime_1.jsx(TimelineList_1.TimelineList, { timeline: shown }) }), jsx_runtime_1.jsx(SplitterHandle_1.SplitterHandle, { onCollapse: noop, allowToCollapse: "none" }), jsx_runtime_1.jsx(SplitterElement_1.SplitterElement, { type: "anti-flexer", sticky: null, children: jsx_runtime_1.jsxs(TimelineScrollable_1.TimelineScrollable, { children: [
110
- jsx_runtime_1.jsx(TimelineTracks_1.TimelineTracks, { timeline: shown, hasBeenCut: hasBeenCut }), jsx_runtime_1.jsx(TimelineInOutPointer_1.TimelineInOutPointer, {}), jsx_runtime_1.jsx(TimelinePlayCursorSyncer_1.TimelinePlayCursorSyncer, {}), jsx_runtime_1.jsx(TimelineDragHandler_1.TimelineDragHandler, {}), jsx_runtime_1.jsx(TimelineTimeIndicators_1.TimelineTimeIndicators, {}), jsx_runtime_1.jsx(TimelineSlider_1.TimelineSlider, {})
111
- ] }) })
112
- ] })
113
- ] })) })
114
- ] }) }));
116
+ return (jsx_runtime_1.jsxs(TimelineClearSelectionArea, { children: [sequences.map((sequence) => {
117
+ if (!sequence.controls || !previewConnected || !sequence.getStack()) {
118
+ return null;
119
+ }
120
+ return (jsx_runtime_1.jsx(SubscribeToNodePaths_1.SubscribeToNodePaths, { overrideId: sequence.controls.overrideId, schema: sequence.controls.schema, getStack: sequence.getStack, effects: sequence.effects }, sequence.id));
121
+ }), jsx_runtime_1.jsx(SequencePropsObserver_1.SequencePropsObserver, {}), jsx_runtime_1.jsx(TimelineSelection_1.TimelineSelectAllKeybindings, { timeline: shown }), jsx_runtime_1.jsx(TimelineHeightContainer_1.TimelineHeightContainer, { shown: shown, hasBeenCut: hasBeenCut, children: isStill ? (jsx_runtime_1.jsx(TimelineList_1.TimelineList, { timeline: shown })) : (jsx_runtime_1.jsxs(TimelineWidthProvider_1.TimelineWidthProvider, { children: [
122
+ jsx_runtime_1.jsx(TimelinePinchZoom_1.TimelinePinchZoom, {}), jsx_runtime_1.jsxs(SplitterContainer_1.SplitterContainer, { orientation: "vertical", defaultFlex: 0.2, id: "names-to-timeline", maxFlex: 0.5, minFlex: 0.15, children: [
123
+ jsx_runtime_1.jsx(SplitterElement_1.SplitterElement, { type: "flexer", sticky: jsx_runtime_1.jsx(TimelineTimeIndicators_1.TimelineTimePlaceholders, {}), children: jsx_runtime_1.jsx(TimelineList_1.TimelineList, { timeline: shown }) }), jsx_runtime_1.jsx(SplitterHandle_1.SplitterHandle, { onCollapse: noop, allowToCollapse: "none" }), jsx_runtime_1.jsx(SplitterElement_1.SplitterElement, { type: "anti-flexer", sticky: null, children: jsx_runtime_1.jsxs(TimelineScrollable_1.TimelineScrollable, { children: [
124
+ jsx_runtime_1.jsx(TimelineTracks_1.TimelineTracks, { timeline: shown, hasBeenCut: hasBeenCut }), jsx_runtime_1.jsx(TimelinePlayCursorSyncer_1.TimelinePlayCursorSyncer, {}), jsx_runtime_1.jsx(TimelineInOutPointer_1.TimelineInOutPointer, {}), jsx_runtime_1.jsx(TimelineTimeIndicators_1.TimelineTimeIndicators, {}), jsx_runtime_1.jsx(TimelineDragHandler_1.TimelineDragHandler, {}), jsx_runtime_1.jsx(TimelineInOutDragHandler_1.TimelineInOutDragHandler, {}), jsx_runtime_1.jsx(TimelineSlider_1.TimelineSlider, {})
125
+ ] }) })
126
+ ] })
127
+ ] })) })
128
+ ] }));
115
129
  };
116
130
  exports.Timeline = react_1.default.memo(TimelineInner);
@@ -0,0 +1,2 @@
1
+ import type React from 'react';
2
+ export declare const TimelineDeleteKeybindings: React.FC;
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TimelineDeleteKeybindings = void 0;
4
+ const react_1 = require("react");
5
+ const remotion_1 = require("remotion");
6
+ const client_id_1 = require("../../helpers/client-id");
7
+ const use_keybinding_1 = require("../../helpers/use-keybinding");
8
+ const delete_selected_timeline_item_1 = require("./delete-selected-timeline-item");
9
+ const duplicate_selected_timeline_item_1 = require("./duplicate-selected-timeline-item");
10
+ const TimelineSelection_1 = require("./TimelineSelection");
11
+ const TimelineDeleteKeybindings = () => {
12
+ const keybindings = (0, use_keybinding_1.useKeybinding)();
13
+ const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
14
+ const { sequences } = (0, react_1.useContext)(remotion_1.Internals.SequenceManager);
15
+ const { overrideIdToNodePathMappings } = (0, react_1.useContext)(remotion_1.Internals.OverrideIdsToNodePathsGettersContext);
16
+ const { setCodeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
17
+ const { canSelect } = (0, TimelineSelection_1.useTimelineSelection)();
18
+ const currentSelection = (0, TimelineSelection_1.useCurrentTimelineSelectionStateAsRef)();
19
+ (0, react_1.useEffect)(() => {
20
+ if (!canSelect || previewServerState.type !== 'connected') {
21
+ return;
22
+ }
23
+ const { clientId } = previewServerState;
24
+ const backspace = keybindings.registerKeybinding({
25
+ event: 'keydown',
26
+ key: 'Backspace',
27
+ callback: () => {
28
+ const { selectedItems, clearSelection } = currentSelection.current;
29
+ if (selectedItems.length === 0) {
30
+ return;
31
+ }
32
+ const deletePromise = (0, delete_selected_timeline_item_1.deleteSelectedTimelineItems)({
33
+ selections: selectedItems,
34
+ sequences,
35
+ overrideIdsToNodePaths: overrideIdToNodePathMappings,
36
+ setCodeValues,
37
+ clientId,
38
+ });
39
+ if (deletePromise === null) {
40
+ return;
41
+ }
42
+ clearSelection();
43
+ deletePromise.catch(() => undefined);
44
+ },
45
+ commandCtrlKey: false,
46
+ preventDefault: true,
47
+ triggerIfInputFieldFocused: false,
48
+ keepRegisteredWhenNotHighestContext: false,
49
+ });
50
+ const duplicate = keybindings.registerKeybinding({
51
+ event: 'keydown',
52
+ key: 'd',
53
+ callback: () => {
54
+ const { selectedItems } = currentSelection.current;
55
+ if (selectedItems.length === 0) {
56
+ return;
57
+ }
58
+ const duplicatePromise = (0, duplicate_selected_timeline_item_1.duplicateSelectedTimelineItems)({
59
+ selections: selectedItems,
60
+ });
61
+ if (duplicatePromise === null) {
62
+ return;
63
+ }
64
+ duplicatePromise.catch(() => undefined);
65
+ },
66
+ commandCtrlKey: true,
67
+ preventDefault: true,
68
+ triggerIfInputFieldFocused: false,
69
+ keepRegisteredWhenNotHighestContext: false,
70
+ });
71
+ return () => {
72
+ backspace.unregister();
73
+ duplicate.unregister();
74
+ };
75
+ }, [
76
+ canSelect,
77
+ currentSelection,
78
+ keybindings,
79
+ overrideIdToNodePathMappings,
80
+ previewServerState,
81
+ sequences,
82
+ setCodeValues,
83
+ ]);
84
+ return null;
85
+ };
86
+ exports.TimelineDeleteKeybindings = TimelineDeleteKeybindings;
@@ -38,21 +38,15 @@ const jsx_runtime_1 = require("react/jsx-runtime");
38
38
  const player_1 = require("@remotion/player");
39
39
  const react_1 = __importStar(require("react"));
40
40
  const remotion_1 = require("remotion");
41
- const get_left_of_timeline_slider_1 = require("../../helpers/get-left-of-timeline-slider");
42
41
  const timeline_layout_1 = require("../../helpers/timeline-layout");
43
- const in_out_1 = require("../../state/in-out");
44
42
  const timeline_zoom_1 = require("../../state/timeline-zoom");
45
43
  const z_index_1 = require("../../state/z-index");
46
- const ContextMenu_1 = require("../ContextMenu");
47
- const ForceSpecificCursor_1 = require("../ForceSpecificCursor");
48
44
  const is_menu_item_1 = require("../Menu/is-menu-item");
49
- const TimelineInOutToggle_1 = require("../TimelineInOutToggle");
50
45
  const timeline_refs_1 = require("./timeline-refs");
51
46
  const timeline_scroll_logic_1 = require("./timeline-scroll-logic");
52
- const TimelineInOutPointer_1 = require("./TimelineInOutPointer");
53
- const TimelineInOutPointerHandle_1 = require("./TimelineInOutPointerHandle");
47
+ const TimelineSelection_1 = require("./TimelineSelection");
54
48
  const TimelineSlider_1 = require("./TimelineSlider");
55
- const TimelineWidthProvider_1 = require("./TimelineWidthProvider");
49
+ const TimelineTimeIndicators_1 = require("./TimelineTimeIndicators");
56
50
  const inner = {
57
51
  overflowY: 'auto',
58
52
  overflowX: 'hidden',
@@ -69,6 +63,7 @@ const style = {
69
63
  height: '100%',
70
64
  userSelect: 'none',
71
65
  WebkitUserSelect: 'none',
66
+ position: 'absolute',
72
67
  };
73
68
  const getClientXWithScroll = (x) => {
74
69
  var _a;
@@ -87,6 +82,7 @@ const TimelineDragHandler = () => {
87
82
  return {
88
83
  ...container,
89
84
  width: 100 * zoom + '%',
85
+ ...(TimelineSelection_1.TIMELINE_TOP_DRAG ? { height: TimelineTimeIndicators_1.TIMELINE_TIME_INDICATOR_HEIGHT } : {}),
90
86
  };
91
87
  }, [canvasContent, zoomMap]);
92
88
  if (!canvasContent || canvasContent.type !== 'composition') {
@@ -105,20 +101,8 @@ const TimelineDragHandlerInner = () => {
105
101
  });
106
102
  const { isHighestContext } = (0, z_index_1.useZIndex)();
107
103
  const setFrame = remotion_1.Internals.useTimelineSetFrame();
108
- const [inOutDragging, setInOutDragging] = (0, react_1.useState)({
109
- dragging: false,
110
- });
111
- const timelineWidth = (0, react_1.useContext)(TimelineWidthProvider_1.TimelineWidthContext);
112
- const get = (0, react_1.useCallback)((frame) => {
113
- if (timelineWidth === null) {
114
- throw new Error('timeline width is not yet determined');
115
- }
116
- return (0, get_left_of_timeline_slider_1.getXPositionOfItemInTimelineImperatively)(frame, videoConfig.durationInFrames, timelineWidth);
117
- }, [timelineWidth, videoConfig.durationInFrames]);
118
104
  const width = (_b = (_a = timeline_refs_1.scrollableRef.current) === null || _a === void 0 ? void 0 : _a.scrollWidth) !== null && _b !== void 0 ? _b : 0;
119
105
  const left = (_c = size === null || size === void 0 ? void 0 : size.left) !== null && _c !== void 0 ? _c : 0;
120
- const { inFrame, outFrame } = (0, in_out_1.useTimelineInOutFramePosition)();
121
- const { setInAndOutFrames } = (0, in_out_1.useTimelineSetInOutFramePosition)();
122
106
  const [dragging, setDragging] = (0, react_1.useState)({
123
107
  dragging: false,
124
108
  });
@@ -143,37 +127,6 @@ const TimelineDragHandlerInner = () => {
143
127
  }
144
128
  document.body.style.userSelect = 'none';
145
129
  document.body.style.webkitUserSelect = 'none';
146
- if (e.target === TimelineInOutPointerHandle_1.inPointerHandle.current) {
147
- if (inFrame === null) {
148
- throw new Error('expected outframe');
149
- }
150
- const inMarker = get(inFrame);
151
- const outMarker = outFrame === null ? Infinity : get(outFrame - 1);
152
- (0, ForceSpecificCursor_1.forceSpecificCursor)('ew-resize');
153
- setInOutDragging({
154
- dragging: 'in',
155
- initialOffset: getClientXWithScroll(e.clientX),
156
- boundaries: [-Infinity, outMarker - inMarker],
157
- });
158
- return;
159
- }
160
- if (e.target === TimelineInOutPointerHandle_1.outPointerHandle.current) {
161
- if (outFrame === null) {
162
- throw new Error('expected outframe');
163
- }
164
- const outMarker = get(outFrame);
165
- const inMarker = inFrame === null ? -Infinity : get(inFrame + 1);
166
- (0, ForceSpecificCursor_1.forceSpecificCursor)('ew-resize');
167
- setInOutDragging({
168
- dragging: 'out',
169
- initialOffset: getClientXWithScroll(e.clientX),
170
- boundaries: [inMarker - outMarker, Infinity],
171
- });
172
- return;
173
- }
174
- if (e.button !== 0) {
175
- return;
176
- }
177
130
  const frame = (0, timeline_scroll_logic_1.getFrameFromX)({
178
131
  clientX: getClientXWithScroll(e.clientX) - left,
179
132
  durationInFrames: videoConfig.durationInFrames,
@@ -186,18 +139,7 @@ const TimelineDragHandlerInner = () => {
186
139
  wasPlaying: playing,
187
140
  });
188
141
  pause();
189
- }, [
190
- isHighestContext,
191
- videoConfig,
192
- left,
193
- width,
194
- seek,
195
- playing,
196
- pause,
197
- inFrame,
198
- get,
199
- outFrame,
200
- ]);
142
+ }, [isHighestContext, videoConfig, left, width, seek, playing, pause]);
201
143
  const onPointerMoveScrubbing = (0, react_1.useCallback)((e) => {
202
144
  var _a;
203
145
  if (!videoConfig) {
@@ -277,45 +219,6 @@ const TimelineDragHandlerInner = () => {
277
219
  seek(frame);
278
220
  }
279
221
  }, [videoConfig, dragging.dragging, left, width, seek]);
280
- const onPointerMoveInOut = (0, react_1.useCallback)((e) => {
281
- if (!videoConfig) {
282
- return;
283
- }
284
- if (!inOutDragging.dragging) {
285
- return;
286
- }
287
- const offset = Math.max(inOutDragging.boundaries[0], Math.min(inOutDragging.boundaries[1], getClientXWithScroll(e.clientX) - inOutDragging.initialOffset));
288
- if (inOutDragging.dragging === 'in') {
289
- if (!TimelineInOutPointerHandle_1.inPointerHandle.current) {
290
- throw new Error('in pointer handle');
291
- }
292
- if (!TimelineInOutPointer_1.inMarkerAreaRef.current) {
293
- throw new Error('expected inMarkerAreaRef');
294
- }
295
- if (!inFrame) {
296
- throw new Error('expected inframes');
297
- }
298
- TimelineInOutPointerHandle_1.inPointerHandle.current.style.transform = `translateX(${get(inFrame) + offset}px)`;
299
- TimelineInOutPointer_1.inMarkerAreaRef.current.style.width =
300
- String(get(inFrame) + offset) + 'px';
301
- }
302
- if (inOutDragging.dragging === 'out') {
303
- if (!TimelineInOutPointerHandle_1.outPointerHandle.current) {
304
- throw new Error('in pointer handle');
305
- }
306
- if (!TimelineInOutPointer_1.outMarkerAreaRef.current) {
307
- throw new Error('in outMarkerAreaRef');
308
- }
309
- if (!outFrame) {
310
- throw new Error('expected outframes');
311
- }
312
- TimelineInOutPointerHandle_1.outPointerHandle.current.style.transform = `translateX(${get(outFrame) + offset}px)`;
313
- TimelineInOutPointer_1.outMarkerAreaRef.current.style.left =
314
- String(get(outFrame) + offset) + 'px';
315
- TimelineInOutPointer_1.outMarkerAreaRef.current.style.width =
316
- String(width - get(outFrame) - offset) + 'px';
317
- }
318
- }, [get, inFrame, inOutDragging, outFrame, videoConfig, width]);
319
222
  const onPointerUpScrubbing = (0, react_1.useCallback)((e) => {
320
223
  stopInterval();
321
224
  document.body.style.userSelect = '';
@@ -344,84 +247,6 @@ const TimelineDragHandlerInner = () => {
344
247
  play();
345
248
  }
346
249
  }, [dragging, left, play, videoConfig, setFrame, width]);
347
- const onPointerUpInOut = (0, react_1.useCallback)((e) => {
348
- document.body.style.userSelect = '';
349
- document.body.style.webkitUserSelect = '';
350
- (0, ForceSpecificCursor_1.stopForcingSpecificCursor)();
351
- if (!videoConfig) {
352
- return;
353
- }
354
- if (!inOutDragging.dragging) {
355
- return;
356
- }
357
- setInOutDragging({
358
- dragging: false,
359
- });
360
- const frame = (0, timeline_scroll_logic_1.getFrameFromX)({
361
- clientX: getClientXWithScroll(e.clientX) - left,
362
- durationInFrames: videoConfig.durationInFrames,
363
- width,
364
- extrapolate: 'extend',
365
- });
366
- if (inOutDragging.dragging === 'in') {
367
- if (frame < 1) {
368
- return setInAndOutFrames((prev) => {
369
- var _a;
370
- return ({
371
- ...prev,
372
- [videoConfig.id]: {
373
- ...((_a = prev[videoConfig.id]) !== null && _a !== void 0 ? _a : TimelineInOutToggle_1.defaultInOutValue),
374
- inFrame: null,
375
- },
376
- });
377
- });
378
- }
379
- const maxFrame = outFrame === null ? Infinity : outFrame - 1;
380
- setInAndOutFrames((prev) => {
381
- var _a;
382
- return ({
383
- ...prev,
384
- [videoConfig.id]: {
385
- ...((_a = prev[videoConfig.id]) !== null && _a !== void 0 ? _a : TimelineInOutToggle_1.defaultInOutValue),
386
- inFrame: Math.min(maxFrame, frame),
387
- },
388
- });
389
- });
390
- }
391
- else {
392
- if (frame > videoConfig.durationInFrames - 2) {
393
- return setInAndOutFrames((prev) => {
394
- var _a;
395
- return ({
396
- ...prev,
397
- [videoConfig.id]: {
398
- ...((_a = prev[videoConfig.id]) !== null && _a !== void 0 ? _a : TimelineInOutToggle_1.defaultInOutValue),
399
- outFrame: null,
400
- },
401
- });
402
- });
403
- }
404
- const minFrame = inFrame === null ? -Infinity : inFrame + 1;
405
- setInAndOutFrames((prev) => {
406
- var _a;
407
- return ({
408
- ...prev,
409
- [videoConfig.id]: {
410
- ...((_a = prev[videoConfig.id]) !== null && _a !== void 0 ? _a : TimelineInOutToggle_1.defaultInOutValue),
411
- outFrame: Math.max(minFrame, frame),
412
- },
413
- });
414
- });
415
- }
416
- }, [
417
- inFrame,
418
- inOutDragging.dragging,
419
- left,
420
- outFrame,
421
- setInAndOutFrames,
422
- videoConfig,
423
- width,
424
- ]);
425
250
  (0, react_1.useEffect)(() => {
426
251
  if (!dragging.dragging) {
427
252
  return;
@@ -433,74 +258,24 @@ const TimelineDragHandlerInner = () => {
433
258
  window.removeEventListener('pointerup', onPointerUpScrubbing);
434
259
  };
435
260
  }, [dragging.dragging, onPointerMoveScrubbing, onPointerUpScrubbing]);
261
+ const ref = (0, react_1.useRef)(null);
436
262
  (0, react_1.useEffect)(() => {
437
- if (inOutDragging.dragging === false) {
263
+ const currentRef = ref.current;
264
+ if (!currentRef) {
438
265
  return;
439
266
  }
440
- window.addEventListener('pointermove', onPointerMoveInOut);
441
- window.addEventListener('pointerup', onPointerUpInOut);
267
+ const { current } = timeline_refs_1.timelineVerticalScroll;
268
+ if (!current) {
269
+ return;
270
+ }
271
+ const onScroll = () => {
272
+ currentRef.style.top = current.scrollTop + 'px';
273
+ };
274
+ current.addEventListener('scroll', onScroll);
442
275
  return () => {
443
- window.removeEventListener('pointermove', onPointerMoveInOut);
444
- window.removeEventListener('pointerup', onPointerUpInOut);
276
+ current.removeEventListener('scroll', onScroll);
445
277
  };
446
- }, [inOutDragging.dragging, onPointerMoveInOut, onPointerUpInOut]);
447
- const inContextMenu = (0, react_1.useMemo)(() => {
448
- return [
449
- {
450
- id: 'hide-in',
451
- keyHint: null,
452
- label: 'Clear In marker',
453
- leftItem: null,
454
- onClick: (_, e) => {
455
- e === null || e === void 0 ? void 0 : e.stopPropagation();
456
- e === null || e === void 0 ? void 0 : e.preventDefault();
457
- setInAndOutFrames((prev) => {
458
- var _a;
459
- return ({
460
- ...prev,
461
- [videoConfig.id]: {
462
- ...((_a = prev[videoConfig.id]) !== null && _a !== void 0 ? _a : TimelineInOutToggle_1.defaultInOutValue),
463
- inFrame: null,
464
- },
465
- });
466
- });
467
- },
468
- quickSwitcherLabel: null,
469
- subMenu: null,
470
- type: 'item',
471
- value: 'hide-in',
472
- },
473
- ];
474
- }, [setInAndOutFrames, videoConfig.id]);
475
- const outContextMenu = (0, react_1.useMemo)(() => {
476
- return [
477
- {
478
- id: 'hide-out',
479
- keyHint: null,
480
- label: 'Clear Out marker',
481
- leftItem: null,
482
- onClick: (_, e) => {
483
- e === null || e === void 0 ? void 0 : e.stopPropagation();
484
- e === null || e === void 0 ? void 0 : e.preventDefault();
485
- setInAndOutFrames((prev) => {
486
- var _a;
487
- return ({
488
- ...prev,
489
- [videoConfig.id]: {
490
- ...((_a = prev[videoConfig.id]) !== null && _a !== void 0 ? _a : TimelineInOutToggle_1.defaultInOutValue),
491
- outFrame: null,
492
- },
493
- });
494
- });
495
- },
496
- quickSwitcherLabel: null,
497
- subMenu: null,
498
- type: 'item',
499
- value: 'hide-out',
500
- },
501
- ];
502
- }, [setInAndOutFrames, videoConfig.id]);
503
- return (jsx_runtime_1.jsxs("div", { style: style, onPointerDown: onPointerDown, children: [
504
- jsx_runtime_1.jsx("div", { style: inner, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME }), inFrame !== null && (jsx_runtime_1.jsx(ContextMenu_1.ContextMenu, { values: inContextMenu, onOpen: null, children: jsx_runtime_1.jsx(TimelineInOutPointerHandle_1.TimelineInOutPointerHandle, { type: "in", atFrame: inFrame, dragging: inOutDragging.dragging === 'in' }) })), outFrame !== null && (jsx_runtime_1.jsx(ContextMenu_1.ContextMenu, { values: outContextMenu, onOpen: null, children: jsx_runtime_1.jsx(TimelineInOutPointerHandle_1.TimelineInOutPointerHandle, { type: "out", dragging: inOutDragging.dragging === 'out', atFrame: outFrame }) }))] }));
278
+ }, []);
279
+ return (jsx_runtime_1.jsx("div", { ref: ref, style: style, onPointerDown: onPointerDown, children: jsx_runtime_1.jsx("div", { style: inner, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME }) }));
505
280
  };
506
281
  const TimelineDragHandlerInnerMemo = react_1.default.memo(TimelineDragHandlerInner);
@@ -3,7 +3,7 @@ import type { SequencePropsSubscriptionKey, SequenceSchema } from 'remotion';
3
3
  import type { CodePosition } from '../../error-overlay/react-overlay/utils/get-source-map';
4
4
  import type { SequenceNodePathInfo } from '../../helpers/get-timeline-sequence-sort-key';
5
5
  import type { GetIsExpanded } from '../ExpandedTracksProvider';
6
- export declare const TimelineEffectGroupRow: React.FC<{
6
+ export declare const TimelineEffectItem: React.FC<{
7
7
  readonly label: string;
8
8
  readonly nodePathInfo: SequenceNodePathInfo;
9
9
  readonly effectIndex: number;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TimelineEffectGroupRow = void 0;
3
+ exports.TimelineEffectItem = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const remotion_1 = require("remotion");
@@ -19,10 +19,9 @@ const rowLabel = {
19
19
  color: 'rgba(255, 255, 255, 0.8)',
20
20
  userSelect: 'none',
21
21
  };
22
- const TimelineEffectGroupRow = ({ label, nodePathInfo, effectIndex, effectSchema, documentationLink, nodePath, validatedLocation, rowDepth, getIsExpanded, toggleTrack, }) => {
22
+ const TimelineEffectItem = ({ label, nodePathInfo, effectIndex, effectSchema, documentationLink, nodePath, validatedLocation, rowDepth, getIsExpanded, toggleTrack, }) => {
23
23
  var _a;
24
24
  var _b;
25
- const [labelHovered, setLabelHovered] = (0, react_1.useState)(false);
26
25
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
27
26
  const previewConnected = previewServerState.type === 'connected';
28
27
  const { codeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeCodeValuesContext);
@@ -51,11 +50,14 @@ const TimelineEffectGroupRow = ({ label, nodePathInfo, effectIndex, effectSchema
51
50
  return;
52
51
  }
53
52
  try {
54
- const result = await (0, call_api_1.callApi)('/api/delete-effect', {
55
- fileName: validatedLocation.source,
56
- sequenceNodePath: nodePath,
57
- effectIndex,
58
- });
53
+ const result = await (0, call_api_1.callApi)('/api/delete-effect', [
54
+ {
55
+ type: 'single-effect',
56
+ fileName: validatedLocation.source,
57
+ sequenceNodePath: nodePath,
58
+ effectIndex,
59
+ },
60
+ ]);
59
61
  if (result.success) {
60
62
  (0, NotificationCenter_1.showNotification)('Removed effect from source file', 2000);
61
63
  }
@@ -71,26 +73,51 @@ const TimelineEffectGroupRow = ({ label, nodePathInfo, effectIndex, effectSchema
71
73
  if (!previewConnected) {
72
74
  return [];
73
75
  }
74
- return [
75
- {
76
+ const items = [];
77
+ if (documentationLink) {
78
+ items.push({
76
79
  type: 'item',
77
- id: 'delete-effect',
80
+ id: 'open-effect-docs',
78
81
  keyHint: null,
79
- label: 'Delete',
82
+ label: 'Open effect docs',
80
83
  leftItem: null,
81
- disabled: deleteDisabled,
84
+ disabled: false,
82
85
  onClick: () => {
83
- if (deleteDisabled) {
84
- return;
85
- }
86
- onDeleteEffectFromSource();
86
+ window.open(documentationLink, '_blank', 'noopener,noreferrer');
87
87
  },
88
88
  quickSwitcherLabel: null,
89
89
  subMenu: null,
90
- value: 'delete-effect',
90
+ value: 'open-effect-docs',
91
+ });
92
+ items.push({
93
+ type: 'divider',
94
+ id: 'open-effect-docs-divider',
95
+ });
96
+ }
97
+ items.push({
98
+ type: 'item',
99
+ id: 'delete-effect',
100
+ keyHint: null,
101
+ label: 'Delete',
102
+ leftItem: null,
103
+ disabled: deleteDisabled,
104
+ onClick: () => {
105
+ if (deleteDisabled) {
106
+ return;
107
+ }
108
+ onDeleteEffectFromSource();
91
109
  },
92
- ];
93
- }, [deleteDisabled, onDeleteEffectFromSource, previewConnected]);
110
+ quickSwitcherLabel: null,
111
+ subMenu: null,
112
+ value: 'delete-effect',
113
+ });
114
+ return items;
115
+ }, [
116
+ deleteDisabled,
117
+ documentationLink,
118
+ onDeleteEffectFromSource,
119
+ previewConnected,
120
+ ]);
94
121
  const onToggle = (0, react_1.useCallback)((type) => {
95
122
  if (!canToggle || previewServerState.type !== 'connected') {
96
123
  return;
@@ -125,7 +152,6 @@ const TimelineEffectGroupRow = ({ label, nodePathInfo, effectIndex, effectSchema
125
152
  height: timeline_layout_1.TREE_GROUP_ROW_HEIGHT,
126
153
  }), []);
127
154
  const labelStyle = (0, react_1.useMemo)(() => {
128
- const hoverEffect = labelHovered && documentationLink !== null;
129
155
  return {
130
156
  ...rowLabel,
131
157
  ...(0, TimelineSelection_1.getTimelineSelectedLabelStyle)(selection.selected, true),
@@ -136,18 +162,9 @@ const TimelineEffectGroupRow = ({ label, nodePathInfo, effectIndex, effectSchema
136
162
  flex: 1,
137
163
  minWidth: 0,
138
164
  paddingRight: timeline_layout_1.EXPANDED_SECTION_PADDING_RIGHT,
139
- textDecoration: hoverEffect ? 'underline' : 'none',
140
- textUnderlineOffset: 2,
141
- cursor: hoverEffect ? 'pointer' : undefined,
142
165
  };
143
- }, [documentationLink, labelHovered, selection.selected]);
144
- const onClickLabel = (0, react_1.useCallback)(() => {
145
- if (documentationLink === null) {
146
- return;
147
- }
148
- window.open(documentationLink, '_blank', 'noopener,noreferrer');
149
- }, [documentationLink]);
150
- const row = (jsx_runtime_1.jsx(TimelineRowChrome_1.TimelineRowChrome, { depth: rowDepth, eye: canToggle ? (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEye, { type: "effect", hidden: isDisabled, onInvoked: onToggle })) : (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEyeSpacer, {})), arrow: jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowButton, { isExpanded: isExpanded, onClick: () => toggleTrack(nodePathInfo), label: `${label} section`, disabled: false }), style: rowStyle, selected: selection.selected, selectable: selection.selectable, onSelect: selection.onSelect, showSelectedBackground: true, containsSelection: false, outerHeight: null, children: jsx_runtime_1.jsx("span", { onPointerEnter: () => setLabelHovered(true), onPointerLeave: () => setLabelHovered(false), onClick: onClickLabel, title: documentationLink ? `Open documentation: ${documentationLink}` : label, style: labelStyle, children: label }) }));
166
+ }, [selection.selected]);
167
+ const row = (jsx_runtime_1.jsx(TimelineRowChrome_1.TimelineRowChrome, { depth: rowDepth, eye: canToggle ? (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEye, { type: "effect", hidden: isDisabled, onInvoked: onToggle })) : (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEyeSpacer, {})), arrow: jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowButton, { isExpanded: isExpanded, onClick: () => toggleTrack(nodePathInfo), label: `${label} section`, disabled: false }), style: rowStyle, selected: selection.selected, selectable: selection.selectable, onSelect: selection.onSelect, showSelectedBackground: true, containsSelection: false, outerHeight: null, children: jsx_runtime_1.jsx("span", { title: label, style: labelStyle, children: label }) }));
151
168
  return previewConnected ? (jsx_runtime_1.jsx(ContextMenu_1.ContextMenu, { values: contextMenuValues, onOpen: selection.selectable ? selection.onSelect : null, children: row })) : (row);
152
169
  };
153
- exports.TimelineEffectGroupRow = TimelineEffectGroupRow;
170
+ exports.TimelineEffectItem = TimelineEffectItem;
@@ -3,10 +3,11 @@ import type { SequencePropsSubscriptionKey } from 'remotion';
3
3
  import type { CodePosition } from '../../error-overlay/react-overlay/utils/get-source-map';
4
4
  import type { SequenceNodePathInfo } from '../../helpers/get-timeline-sequence-sort-key';
5
5
  import type { EffectSchemaFieldInfo } from '../../helpers/timeline-layout';
6
- export declare const TimelineEffectFieldRow: React.FC<{
6
+ export declare const TimelineEffectPropItem: React.FC<{
7
7
  readonly field: EffectSchemaFieldInfo;
8
8
  readonly validatedLocation: CodePosition;
9
9
  readonly rowDepth: number;
10
10
  readonly nodePath: SequencePropsSubscriptionKey;
11
11
  readonly nodePathInfo: SequenceNodePathInfo;
12
+ readonly keyframeDisplayOffset: number;
12
13
  }>;