@remotion/studio 4.0.469 → 4.0.471
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.
- package/dist/Studio.js +1 -1
- package/dist/api/save-render-output.js +3 -12
- package/dist/components/AudioWaveform.js +19 -2
- package/dist/components/ContextMenu.d.ts +7 -2
- package/dist/components/ContextMenu.js +53 -9
- package/dist/components/EditorContent.js +5 -4
- package/dist/components/Menu/MenuItem.d.ts +1 -1
- package/dist/components/MenuBuildIndicator.js +0 -1
- package/dist/components/NewComposition/InputDragger.js +1 -0
- package/dist/components/Preview.js +6 -2
- package/dist/components/SelectedOutlineOverlay.d.ts +49 -0
- package/dist/components/SelectedOutlineOverlay.js +710 -0
- package/dist/components/Timeline/Timeline.js +102 -13
- package/dist/components/Timeline/TimelineDeleteKeybindings.d.ts +2 -0
- package/dist/components/Timeline/TimelineDeleteKeybindings.js +101 -0
- package/dist/components/Timeline/TimelineDragHandler.js +20 -244
- package/dist/components/Timeline/{TimelineEffectGroupRow.d.ts → TimelineEffectItem.d.ts} +1 -1
- package/dist/components/Timeline/TimelineEffectItem.js +323 -0
- package/dist/components/Timeline/{TimelineEffectFieldRow.d.ts → TimelineEffectPropItem.d.ts} +2 -1
- package/dist/components/Timeline/{TimelineEffectFieldRow.js → TimelineEffectPropItem.js} +97 -8
- package/dist/components/Timeline/TimelineExpandArrowButton.js +5 -1
- package/dist/components/Timeline/TimelineExpandedKeyframeRow.js +37 -5
- package/dist/components/Timeline/TimelineExpandedRow.d.ts +1 -0
- package/dist/components/Timeline/TimelineExpandedRow.js +9 -7
- package/dist/components/Timeline/TimelineExpandedSection.d.ts +1 -0
- package/dist/components/Timeline/TimelineExpandedSection.js +2 -2
- package/dist/components/Timeline/TimelineInOutDragHandler.d.ts +2 -0
- package/dist/components/Timeline/TimelineInOutDragHandler.js +324 -0
- package/dist/components/Timeline/TimelineInOutPointer.js +3 -1
- package/dist/components/Timeline/TimelineInOutPointerHandle.d.ts +1 -0
- package/dist/components/Timeline/TimelineInOutPointerHandle.js +5 -4
- package/dist/components/Timeline/TimelineKeyframeControls.d.ts +17 -0
- package/dist/components/Timeline/TimelineKeyframeControls.js +222 -0
- package/dist/components/Timeline/TimelineKeyframeDiamond.js +7 -6
- package/dist/components/Timeline/TimelineKeyframedValue.d.ts +8 -0
- package/dist/components/Timeline/TimelineKeyframedValue.js +36 -0
- package/dist/components/Timeline/TimelineList.js +3 -15
- package/dist/components/Timeline/TimelineRowChrome.d.ts +6 -1
- package/dist/components/Timeline/TimelineRowChrome.js +25 -7
- package/dist/components/Timeline/TimelineSelection.d.ts +53 -9
- package/dist/components/Timeline/TimelineSelection.js +305 -48
- package/dist/components/Timeline/TimelineSequence.d.ts +2 -0
- package/dist/components/Timeline/TimelineSequence.js +18 -6
- package/dist/components/Timeline/TimelineSequenceFrame.js +1 -0
- package/dist/components/Timeline/{TimelineListItem.d.ts → TimelineSequenceItem.d.ts} +2 -1
- package/dist/components/Timeline/{TimelineListItem.js → TimelineSequenceItem.js} +140 -34
- package/dist/components/Timeline/{TimelineFieldRow.d.ts → TimelineSequencePropItem.d.ts} +2 -1
- package/dist/components/Timeline/{TimelineFieldRow.js → TimelineSequencePropItem.js} +81 -5
- package/dist/components/Timeline/TimelineTimeIndicators.js +0 -1
- package/dist/components/Timeline/TimelineTrack.js +3 -1
- package/dist/components/Timeline/TimelineTranslateField.js +14 -22
- package/dist/components/Timeline/call-add-keyframe.d.ts +23 -0
- package/dist/components/Timeline/call-add-keyframe.js +54 -0
- package/dist/components/Timeline/call-delete-keyframe.d.ts +37 -0
- package/dist/components/Timeline/call-delete-keyframe.js +122 -0
- package/dist/components/Timeline/delete-selected-keyframe.d.ts +21 -0
- package/dist/components/Timeline/delete-selected-keyframe.js +92 -0
- package/dist/components/Timeline/delete-selected-timeline-item.d.ts +17 -0
- package/dist/components/Timeline/delete-selected-timeline-item.js +178 -0
- package/dist/components/Timeline/duplicate-selected-timeline-item.d.ts +13 -0
- package/dist/components/Timeline/duplicate-selected-timeline-item.js +66 -0
- package/dist/components/Timeline/find-track-for-node-path-info.d.ts +7 -0
- package/dist/components/Timeline/find-track-for-node-path-info.js +13 -0
- package/dist/components/Timeline/get-keyframe-navigation.d.ts +9 -0
- package/dist/components/Timeline/get-keyframe-navigation.js +26 -0
- package/dist/components/Timeline/parse-keyframe-field-from-node-path.d.ts +8 -0
- package/dist/components/Timeline/parse-keyframe-field-from-node-path.js +26 -0
- package/dist/components/Timeline/reset-selected-timeline-props.d.ts +38 -0
- package/dist/components/Timeline/reset-selected-timeline-props.js +143 -0
- package/dist/components/Timeline/save-sequence-prop.d.ts +14 -2
- package/dist/components/Timeline/save-sequence-prop.js +42 -7
- package/dist/components/Timeline/sequence-props-subscription-store.d.ts +3 -2
- package/dist/components/Timeline/sequence-props-subscription-store.js +2 -1
- package/dist/components/Timeline/timeline-row-layout.d.ts +1 -0
- package/dist/components/Timeline/timeline-row-layout.js +2 -1
- package/dist/components/Timeline/timeline-scroll-logic.js +3 -3
- package/dist/components/Timeline/timeline-translate-utils.d.ts +2 -0
- package/dist/components/Timeline/timeline-translate-utils.js +20 -0
- package/dist/components/Timeline/use-expanded-track-keyframe-rows.js +10 -3
- package/dist/components/Timeline/use-sequence-props-subscription.js +2 -1
- package/dist/components/composition-menu-items.js +32 -1
- package/dist/error-overlay/remotion-overlay/OpenInEditor.js +0 -1
- package/dist/esm/{chunk-1mp51e0w.js → chunk-z0z9d4r0.js} +10422 -5958
- package/dist/esm/internals.mjs +10422 -5958
- package/dist/esm/previewEntry.mjs +10419 -5953
- package/dist/esm/renderEntry.mjs +3 -1
- package/dist/helpers/format-file-location.d.ts +9 -0
- package/dist/helpers/format-file-location.js +27 -0
- package/dist/helpers/get-box-quads-polyfill-internals.d.ts +82 -0
- package/dist/helpers/get-box-quads-polyfill-internals.js +2395 -0
- package/dist/helpers/get-box-quads-ponyfill.d.ts +10 -0
- package/dist/helpers/get-box-quads-ponyfill.js +23 -0
- package/dist/helpers/get-left-of-timeline-slider.js +1 -1
- package/dist/helpers/get-timeline-sequence-layout.js +10 -11
- package/dist/helpers/open-in-editor.d.ts +20 -2
- package/dist/helpers/open-in-editor.js +53 -30
- package/dist/helpers/use-menu-structure.js +8 -17
- package/dist/renderEntry.js +2 -2
- package/dist/state/z-index.js +5 -2
- package/package.json +10 -10
- package/dist/components/Timeline/TimelineEffectGroupRow.js +0 -153
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.useTimelineRowContainsSelection = exports.useTimelineKeyframeSelection = exports.useTimelineRowSelection = exports.useTimelineSelection = exports.TimelineSelectionProvider = exports.SELECTION_ENABLED = exports.
|
|
3
|
+
exports.useTimelineRowContainsSelection = exports.useTimelineKeyframeSelection = exports.useTimelineRowSelection = exports.useCurrentTimelineSelectionStateAsRef = exports.useTimelineSelection = exports.TimelineSelectionProvider = exports.TimelineSelectAllKeybindings = exports.getTimelineSequenceSelectionKey = exports.getSelectableTimelineSequenceSelections = exports.getTimelineSelectionFromNodePathInfo = exports.getTimelineSelectionAfterInteraction = exports.isTimelineSelectionModifierEvent = exports.ENABLE_OUTLINES = exports.TIMELINE_TOP_DRAG = exports.SELECTION_ENABLED = exports.getTimelineSelectedTrackHighlightStyle = exports.getTimelineColor = exports.getTimelineSelectedLabelStyle = exports.TIMELINE_SELECTED_LABEL_HORIZONTAL_PADDING = exports.TIMELINE_SELECTED_LABEL_TEXT = exports.TIMELINE_SELECTED_LABEL_BACKGROUND = exports.TIMELINE_SELECTED_BACKGROUND = void 0;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
const studio_shared_1 = require("@remotion/studio-shared");
|
|
6
6
|
const react_1 = require("react");
|
|
7
7
|
const client_id_1 = require("../../helpers/client-id");
|
|
8
8
|
const timeline_layout_1 = require("../../helpers/timeline-layout");
|
|
9
9
|
const timeline_node_path_key_1 = require("../../helpers/timeline-node-path-key");
|
|
10
|
+
const use_keybinding_1 = require("../../helpers/use-keybinding");
|
|
11
|
+
const TimelineDeleteKeybindings_1 = require("./TimelineDeleteKeybindings");
|
|
10
12
|
exports.TIMELINE_SELECTED_BACKGROUND = '#3B3F42';
|
|
11
13
|
exports.TIMELINE_SELECTED_LABEL_BACKGROUND = '#B0B0B0';
|
|
12
14
|
exports.TIMELINE_SELECTED_LABEL_TEXT = 'black';
|
|
@@ -31,99 +33,351 @@ const getTimelineColor = (selected, subcategory) => {
|
|
|
31
33
|
: 'rgba(255, 255, 255, 0.8)';
|
|
32
34
|
};
|
|
33
35
|
exports.getTimelineColor = getTimelineColor;
|
|
34
|
-
|
|
36
|
+
const getTimelineSelectedTrackHighlightStyle = (timelineWidth) => ({
|
|
35
37
|
backgroundColor: exports.TIMELINE_SELECTED_BACKGROUND,
|
|
36
38
|
bottom: 0,
|
|
37
39
|
left: -timeline_layout_1.TIMELINE_PADDING,
|
|
38
40
|
pointerEvents: 'none',
|
|
39
41
|
position: 'absolute',
|
|
40
|
-
right: -timeline_layout_1.TIMELINE_PADDING,
|
|
41
42
|
top: 0,
|
|
42
|
-
|
|
43
|
+
width: timelineWidth,
|
|
44
|
+
});
|
|
45
|
+
exports.getTimelineSelectedTrackHighlightStyle = getTimelineSelectedTrackHighlightStyle;
|
|
43
46
|
exports.SELECTION_ENABLED = false;
|
|
44
|
-
|
|
47
|
+
exports.TIMELINE_TOP_DRAG = false;
|
|
48
|
+
exports.ENABLE_OUTLINES = false;
|
|
49
|
+
const isTimelineSelectionModifierEvent = ({ shiftKey, metaKey, ctrlKey, }) => {
|
|
50
|
+
return shiftKey || metaKey || ctrlKey;
|
|
51
|
+
};
|
|
52
|
+
exports.isTimelineSelectionModifierEvent = isTimelineSelectionModifierEvent;
|
|
53
|
+
const getTimelineSelectionType = (item) => item.type;
|
|
54
|
+
const getTimelineSelectionAnchor = (selectedItems, previousAnchor, targetType) => {
|
|
55
|
+
if (previousAnchor &&
|
|
56
|
+
getTimelineSelectionType(previousAnchor) === targetType) {
|
|
57
|
+
return previousAnchor;
|
|
58
|
+
}
|
|
59
|
+
for (let i = selectedItems.length - 1; i >= 0; i--) {
|
|
60
|
+
const candidate = selectedItems[i];
|
|
61
|
+
if (getTimelineSelectionType(candidate) === targetType) {
|
|
62
|
+
return candidate;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return null;
|
|
66
|
+
};
|
|
67
|
+
const getRangeSelection = ({ anchor, clickedItem, allSelectableItems, }) => {
|
|
68
|
+
const anchorKey = getTimelineSelectionKey(anchor);
|
|
69
|
+
const clickedKey = getTimelineSelectionKey(clickedItem);
|
|
70
|
+
const orderedOfType = allSelectableItems.filter((item) => getTimelineSelectionType(item) === clickedItem.type);
|
|
71
|
+
const anchorIndex = orderedOfType.findIndex((item) => getTimelineSelectionKey(item) === anchorKey);
|
|
72
|
+
const clickedIndex = orderedOfType.findIndex((item) => getTimelineSelectionKey(item) === clickedKey);
|
|
73
|
+
if (anchorIndex === -1 || clickedIndex === -1) {
|
|
74
|
+
return [clickedItem];
|
|
75
|
+
}
|
|
76
|
+
const [from, to] = anchorIndex < clickedIndex
|
|
77
|
+
? [anchorIndex, clickedIndex]
|
|
78
|
+
: [clickedIndex, anchorIndex];
|
|
79
|
+
return orderedOfType.slice(from, to + 1);
|
|
80
|
+
};
|
|
81
|
+
const getTimelineSelectionAfterInteraction = ({ currentState, clickedItem, interaction, allSelectableItems, }) => {
|
|
82
|
+
const { selectedItems, anchor: previousAnchor } = currentState;
|
|
83
|
+
const clickedType = getTimelineSelectionType(clickedItem);
|
|
84
|
+
const nextAnchor = getTimelineSelectionAnchor(selectedItems, previousAnchor, clickedType);
|
|
85
|
+
const clickedKey = getTimelineSelectionKey(clickedItem);
|
|
86
|
+
if (interaction.shiftKey && nextAnchor) {
|
|
87
|
+
return {
|
|
88
|
+
selectedItems: getRangeSelection({
|
|
89
|
+
anchor: nextAnchor,
|
|
90
|
+
clickedItem,
|
|
91
|
+
allSelectableItems,
|
|
92
|
+
}),
|
|
93
|
+
anchor: nextAnchor,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
if (interaction.toggleKey) {
|
|
97
|
+
const sameTypeItems = selectedItems.filter((item) => getTimelineSelectionType(item) === clickedType);
|
|
98
|
+
const existingKeySet = new Set(sameTypeItems.map(getTimelineSelectionKey));
|
|
99
|
+
if (existingKeySet.has(clickedKey)) {
|
|
100
|
+
const toggledSelection = sameTypeItems.filter((item) => getTimelineSelectionKey(item) !== clickedKey);
|
|
101
|
+
return {
|
|
102
|
+
selectedItems: toggledSelection,
|
|
103
|
+
anchor: toggledSelection.length === 0 ? null : clickedItem,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
const selectableOrderMap = new Map(allSelectableItems
|
|
107
|
+
.filter((item) => getTimelineSelectionType(item) === clickedType)
|
|
108
|
+
.map((item, index) => [getTimelineSelectionKey(item), index]));
|
|
109
|
+
const extendedSelection = [...sameTypeItems, clickedItem].sort((a, b) => {
|
|
110
|
+
var _a, _b;
|
|
111
|
+
return (((_a = selectableOrderMap.get(getTimelineSelectionKey(a))) !== null && _a !== void 0 ? _a : 0) -
|
|
112
|
+
((_b = selectableOrderMap.get(getTimelineSelectionKey(b))) !== null && _b !== void 0 ? _b : 0));
|
|
113
|
+
});
|
|
114
|
+
return {
|
|
115
|
+
selectedItems: extendedSelection,
|
|
116
|
+
anchor: clickedItem,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
return {
|
|
120
|
+
selectedItems: [clickedItem],
|
|
121
|
+
anchor: clickedItem,
|
|
122
|
+
};
|
|
123
|
+
};
|
|
124
|
+
exports.getTimelineSelectionAfterInteraction = getTimelineSelectionAfterInteraction;
|
|
125
|
+
const defaultTimelineSelectionContextValue = {
|
|
45
126
|
canSelect: false,
|
|
127
|
+
selectedItems: [],
|
|
46
128
|
isSelected: () => false,
|
|
47
129
|
selectItem: () => undefined,
|
|
130
|
+
selectItems: () => undefined,
|
|
131
|
+
registerSelectableItem: () => () => undefined,
|
|
48
132
|
containsSelection: () => false,
|
|
49
133
|
clearSelection: () => undefined,
|
|
50
|
-
}
|
|
134
|
+
};
|
|
135
|
+
const TimelineSelectionContext = (0, react_1.createContext)(defaultTimelineSelectionContextValue);
|
|
136
|
+
const CurrentTimelineSelectionContext = (0, react_1.createContext)(null);
|
|
137
|
+
const parseEffectIndex = (effectIndex) => {
|
|
138
|
+
const parsed = Number(effectIndex);
|
|
139
|
+
if (!Number.isInteger(parsed) || parsed < 0) {
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
return parsed;
|
|
143
|
+
};
|
|
144
|
+
const getTimelineSelectionFromNodePathInfo = (nodePathInfo) => {
|
|
145
|
+
if (nodePathInfo === null) {
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
const { auxiliaryKeys } = nodePathInfo;
|
|
149
|
+
if (auxiliaryKeys.length === 0) {
|
|
150
|
+
return { type: 'sequence', nodePathInfo };
|
|
151
|
+
}
|
|
152
|
+
if (auxiliaryKeys.length === 2 && auxiliaryKeys[0] === 'controls') {
|
|
153
|
+
return { type: 'sequence-prop', nodePathInfo, key: auxiliaryKeys[1] };
|
|
154
|
+
}
|
|
155
|
+
if (auxiliaryKeys.length === 1 && auxiliaryKeys[0] === 'effects') {
|
|
156
|
+
return { type: 'sequence-all-effects', nodePathInfo };
|
|
157
|
+
}
|
|
158
|
+
if (auxiliaryKeys[0] === 'effects') {
|
|
159
|
+
const effectIndex = parseEffectIndex(auxiliaryKeys[1]);
|
|
160
|
+
if (effectIndex === null) {
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
if (auxiliaryKeys.length === 2) {
|
|
164
|
+
return { type: 'sequence-effect', nodePathInfo, i: effectIndex };
|
|
165
|
+
}
|
|
166
|
+
if (auxiliaryKeys.length === 3) {
|
|
167
|
+
return {
|
|
168
|
+
type: 'sequence-effect-prop',
|
|
169
|
+
nodePathInfo,
|
|
170
|
+
i: effectIndex,
|
|
171
|
+
key: auxiliaryKeys[2],
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return null;
|
|
176
|
+
};
|
|
177
|
+
exports.getTimelineSelectionFromNodePathInfo = getTimelineSelectionFromNodePathInfo;
|
|
51
178
|
const getTimelineSelectionKey = (item) => {
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
179
|
+
const sequenceKey = (0, exports.getTimelineSequenceSelectionKey)(item.nodePathInfo);
|
|
180
|
+
switch (item.type) {
|
|
181
|
+
case 'sequence':
|
|
182
|
+
return `${sequenceKey}.sequence`;
|
|
183
|
+
case 'sequence-prop':
|
|
184
|
+
return `${sequenceKey}.sequence-prop.${item.key}`;
|
|
185
|
+
case 'sequence-all-effects':
|
|
186
|
+
return `${sequenceKey}.sequence-all-effects`;
|
|
187
|
+
case 'sequence-effect':
|
|
188
|
+
return `${sequenceKey}.sequence-effect.${item.i}`;
|
|
189
|
+
case 'sequence-effect-prop':
|
|
190
|
+
return `${sequenceKey}.sequence-effect-prop.${item.i}.${item.key}`;
|
|
191
|
+
case 'keyframe':
|
|
192
|
+
return `${(0, timeline_node_path_key_1.timelineNodePathInfoToKey)(item.nodePathInfo)}.keyframe.${item.frame}`;
|
|
193
|
+
default:
|
|
194
|
+
throw new Error(`Unexpected timeline selection type: ${item}`);
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
const nodePathDescendsFrom = (descendant, ancestor) => {
|
|
198
|
+
if ((0, studio_shared_1.stringifySequenceExpandedRowKey)(descendant.sequenceSubscriptionKey) !==
|
|
199
|
+
(0, studio_shared_1.stringifySequenceExpandedRowKey)(ancestor.sequenceSubscriptionKey)) {
|
|
200
|
+
return false;
|
|
55
201
|
}
|
|
56
|
-
|
|
202
|
+
if (descendant.index !== ancestor.index) {
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
// Must be strictly deeper than `ancestor` (i.e. a descendant), not the same row.
|
|
206
|
+
if (descendant.auxiliaryKeys.length <= ancestor.auxiliaryKeys.length) {
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
return ancestor.auxiliaryKeys.every((key, i) => descendant.auxiliaryKeys[i] === key);
|
|
210
|
+
};
|
|
211
|
+
const getSelectableTimelineSequenceSelections = (tracks) => {
|
|
212
|
+
return tracks.flatMap((track) => {
|
|
213
|
+
if (track.nodePathInfo === null ||
|
|
214
|
+
track.nodePathInfo.auxiliaryKeys.length > 0) {
|
|
215
|
+
return [];
|
|
216
|
+
}
|
|
217
|
+
return [{ type: 'sequence', nodePathInfo: track.nodePathInfo }];
|
|
218
|
+
});
|
|
219
|
+
};
|
|
220
|
+
exports.getSelectableTimelineSequenceSelections = getSelectableTimelineSequenceSelections;
|
|
221
|
+
const getTimelineSequenceSelectionKey = (nodePathInfo) => (0, timeline_node_path_key_1.timelineNodePathInfoToKey)({ ...nodePathInfo, auxiliaryKeys: [] });
|
|
222
|
+
exports.getTimelineSequenceSelectionKey = getTimelineSequenceSelectionKey;
|
|
223
|
+
const TimelineSelectAllKeybindings = ({ timeline }) => {
|
|
224
|
+
const keybindings = (0, use_keybinding_1.useKeybinding)();
|
|
225
|
+
const { canSelect } = (0, exports.useTimelineSelection)();
|
|
226
|
+
const currentSelection = (0, exports.useCurrentTimelineSelectionStateAsRef)();
|
|
227
|
+
const selectableSequenceSelections = (0, react_1.useMemo)(() => (0, exports.getSelectableTimelineSequenceSelections)(timeline), [timeline]);
|
|
228
|
+
const selectableSequenceSelectionsRef = (0, react_1.useRef)(selectableSequenceSelections);
|
|
229
|
+
selectableSequenceSelectionsRef.current = selectableSequenceSelections;
|
|
230
|
+
(0, react_1.useEffect)(() => {
|
|
231
|
+
if (!canSelect) {
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
const selectAll = keybindings.registerKeybinding({
|
|
235
|
+
event: 'keydown',
|
|
236
|
+
key: 'a',
|
|
237
|
+
callback: () => {
|
|
238
|
+
const latestSelectableSequenceSelections = selectableSequenceSelectionsRef.current;
|
|
239
|
+
if (latestSelectableSequenceSelections.length === 0) {
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
currentSelection.current.selectItems(latestSelectableSequenceSelections);
|
|
243
|
+
},
|
|
244
|
+
commandCtrlKey: true,
|
|
245
|
+
preventDefault: true,
|
|
246
|
+
triggerIfInputFieldFocused: false,
|
|
247
|
+
keepRegisteredWhenNotHighestContext: false,
|
|
248
|
+
});
|
|
249
|
+
return () => {
|
|
250
|
+
selectAll.unregister();
|
|
251
|
+
};
|
|
252
|
+
}, [canSelect, currentSelection, keybindings]);
|
|
253
|
+
return null;
|
|
57
254
|
};
|
|
255
|
+
exports.TimelineSelectAllKeybindings = TimelineSelectAllKeybindings;
|
|
58
256
|
const TimelineSelectionProvider = ({ children }) => {
|
|
59
257
|
const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
|
|
60
258
|
const canSelect = exports.SELECTION_ENABLED &&
|
|
61
259
|
previewServerState.type === 'connected' &&
|
|
62
260
|
!window.remotion_isReadOnlyStudio;
|
|
63
|
-
const [
|
|
261
|
+
const [selectedItems, setSelectedItems] = (0, react_1.useState)([]);
|
|
262
|
+
const selectionAnchor = (0, react_1.useRef)(null);
|
|
263
|
+
const selectableItemsOrder = (0, react_1.useRef)(new Map());
|
|
264
|
+
const selectableItems = (0, react_1.useRef)(new Map());
|
|
265
|
+
const registrationCounter = (0, react_1.useRef)(0);
|
|
64
266
|
(0, react_1.useEffect)(() => {
|
|
65
267
|
if (!canSelect) {
|
|
66
|
-
|
|
268
|
+
setSelectedItems([]);
|
|
67
269
|
}
|
|
68
270
|
}, [canSelect]);
|
|
271
|
+
const selectedKeys = (0, react_1.useMemo)(() => new Set(selectedItems.map(getTimelineSelectionKey)), [selectedItems]);
|
|
69
272
|
const isSelected = (0, react_1.useCallback)((item) => {
|
|
70
|
-
return
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
273
|
+
return selectedKeys.has(getTimelineSelectionKey(item));
|
|
274
|
+
}, [selectedKeys]);
|
|
275
|
+
const selectItem = (0, react_1.useCallback)((item, interaction = {
|
|
276
|
+
shiftKey: false,
|
|
277
|
+
toggleKey: false,
|
|
278
|
+
}) => {
|
|
279
|
+
if (!canSelect) {
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
setSelectedItems((currentSelectedItems) => {
|
|
283
|
+
const orderedSelectableItems = [
|
|
284
|
+
...selectableItems.current.values(),
|
|
285
|
+
].sort((a, b) => {
|
|
286
|
+
var _a, _b;
|
|
287
|
+
return (((_a = selectableItemsOrder.current.get(getTimelineSelectionKey(a))) !== null && _a !== void 0 ? _a : 0) -
|
|
288
|
+
((_b = selectableItemsOrder.current.get(getTimelineSelectionKey(b))) !== null && _b !== void 0 ? _b : 0));
|
|
289
|
+
});
|
|
290
|
+
const nextState = (0, exports.getTimelineSelectionAfterInteraction)({
|
|
291
|
+
currentState: {
|
|
292
|
+
selectedItems: currentSelectedItems,
|
|
293
|
+
anchor: selectionAnchor.current,
|
|
294
|
+
},
|
|
295
|
+
clickedItem: item,
|
|
296
|
+
interaction,
|
|
297
|
+
allSelectableItems: orderedSelectableItems,
|
|
298
|
+
});
|
|
299
|
+
selectionAnchor.current = nextState.anchor;
|
|
300
|
+
return nextState.selectedItems;
|
|
301
|
+
});
|
|
302
|
+
}, [canSelect]);
|
|
303
|
+
const selectItems = (0, react_1.useCallback)((items) => {
|
|
76
304
|
if (!canSelect) {
|
|
77
305
|
return;
|
|
78
306
|
}
|
|
79
|
-
|
|
307
|
+
selectionAnchor.current =
|
|
308
|
+
items.length === 0 ? null : items[items.length - 1];
|
|
309
|
+
setSelectedItems(items);
|
|
80
310
|
}, [canSelect]);
|
|
311
|
+
const registerSelectableItem = (0, react_1.useCallback)((item) => {
|
|
312
|
+
const key = getTimelineSelectionKey(item);
|
|
313
|
+
const registrationOrder = registrationCounter.current;
|
|
314
|
+
registrationCounter.current += 1;
|
|
315
|
+
selectableItems.current.set(key, item);
|
|
316
|
+
selectableItemsOrder.current.set(key, registrationOrder);
|
|
317
|
+
return () => {
|
|
318
|
+
selectableItems.current.delete(key);
|
|
319
|
+
selectableItemsOrder.current.delete(key);
|
|
320
|
+
};
|
|
321
|
+
}, []);
|
|
81
322
|
const clearSelection = (0, react_1.useCallback)(() => {
|
|
82
|
-
|
|
323
|
+
selectionAnchor.current = null;
|
|
324
|
+
setSelectedItems([]);
|
|
83
325
|
}, []);
|
|
84
326
|
const containsSelection = (0, react_1.useCallback)((nodePathInfo) => {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}
|
|
88
|
-
const selectedNodePath = selectedItem.nodePathInfo;
|
|
89
|
-
if ((0, studio_shared_1.stringifySequenceExpandedRowKey)(selectedNodePath.sequenceSubscriptionKey) !==
|
|
90
|
-
(0, studio_shared_1.stringifySequenceExpandedRowKey)(nodePathInfo.sequenceSubscriptionKey)) {
|
|
91
|
-
return false;
|
|
92
|
-
}
|
|
93
|
-
if (selectedNodePath.index !== nodePathInfo.index) {
|
|
94
|
-
return false;
|
|
95
|
-
}
|
|
96
|
-
// Selection must be strictly deeper than this node (i.e. a descendant),
|
|
97
|
-
// not the same row.
|
|
98
|
-
if (selectedNodePath.auxiliaryKeys.length <=
|
|
99
|
-
nodePathInfo.auxiliaryKeys.length) {
|
|
100
|
-
return false;
|
|
101
|
-
}
|
|
102
|
-
return nodePathInfo.auxiliaryKeys.every((key, i) => selectedNodePath.auxiliaryKeys[i] === key);
|
|
103
|
-
}, [selectedItem]);
|
|
327
|
+
return selectedItems.some((selected) => nodePathDescendsFrom(selected.nodePathInfo, nodePathInfo));
|
|
328
|
+
}, [selectedItems]);
|
|
104
329
|
const value = (0, react_1.useMemo)(() => ({
|
|
105
330
|
canSelect,
|
|
331
|
+
selectedItems,
|
|
332
|
+
isSelected,
|
|
333
|
+
selectItem,
|
|
334
|
+
selectItems,
|
|
335
|
+
registerSelectableItem,
|
|
336
|
+
containsSelection,
|
|
337
|
+
clearSelection,
|
|
338
|
+
}), [
|
|
339
|
+
canSelect,
|
|
340
|
+
selectedItems,
|
|
106
341
|
isSelected,
|
|
107
342
|
selectItem,
|
|
343
|
+
selectItems,
|
|
344
|
+
registerSelectableItem,
|
|
108
345
|
containsSelection,
|
|
109
346
|
clearSelection,
|
|
110
|
-
|
|
111
|
-
|
|
347
|
+
]);
|
|
348
|
+
const currentSelection = (0, react_1.useRef)(value);
|
|
349
|
+
currentSelection.current = value;
|
|
350
|
+
return (jsx_runtime_1.jsx(CurrentTimelineSelectionContext.Provider, { value: currentSelection, children: jsx_runtime_1.jsxs(TimelineSelectionContext.Provider, { value: value, children: [children, jsx_runtime_1.jsx(TimelineDeleteKeybindings_1.TimelineDeleteKeybindings, {})
|
|
351
|
+
] }) }));
|
|
112
352
|
};
|
|
113
353
|
exports.TimelineSelectionProvider = TimelineSelectionProvider;
|
|
114
354
|
const useTimelineSelection = () => {
|
|
115
355
|
return (0, react_1.useContext)(TimelineSelectionContext);
|
|
116
356
|
};
|
|
117
357
|
exports.useTimelineSelection = useTimelineSelection;
|
|
358
|
+
const useCurrentTimelineSelectionStateAsRef = () => {
|
|
359
|
+
const currentSelection = (0, react_1.useContext)(CurrentTimelineSelectionContext);
|
|
360
|
+
if (currentSelection === null) {
|
|
361
|
+
throw new Error('useCurrentTimelineSelectionStateAsRef must be used inside TimelineSelectionProvider');
|
|
362
|
+
}
|
|
363
|
+
return currentSelection;
|
|
364
|
+
};
|
|
365
|
+
exports.useCurrentTimelineSelectionStateAsRef = useCurrentTimelineSelectionStateAsRef;
|
|
118
366
|
const useTimelineRowSelection = (nodePathInfo) => {
|
|
119
|
-
const { canSelect, isSelected, selectItem } = (0, exports.useTimelineSelection)();
|
|
120
|
-
const selectionItem = (0, react_1.useMemo)(() =>
|
|
367
|
+
const { canSelect, isSelected, selectItem, registerSelectableItem } = (0, exports.useTimelineSelection)();
|
|
368
|
+
const selectionItem = (0, react_1.useMemo)(() => (0, exports.getTimelineSelectionFromNodePathInfo)(nodePathInfo), [nodePathInfo]);
|
|
369
|
+
(0, react_1.useEffect)(() => {
|
|
370
|
+
if (selectionItem === null) {
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
return registerSelectableItem(selectionItem);
|
|
374
|
+
}, [registerSelectableItem, selectionItem]);
|
|
121
375
|
const selected = selectionItem === null ? false : isSelected(selectionItem);
|
|
122
|
-
const onSelect = (0, react_1.useCallback)(() => {
|
|
376
|
+
const onSelect = (0, react_1.useCallback)((interaction) => {
|
|
123
377
|
if (selectionItem === null) {
|
|
124
378
|
return;
|
|
125
379
|
}
|
|
126
|
-
selectItem(selectionItem);
|
|
380
|
+
selectItem(selectionItem, interaction);
|
|
127
381
|
}, [selectItem, selectionItem]);
|
|
128
382
|
return {
|
|
129
383
|
onSelect,
|
|
@@ -133,15 +387,18 @@ const useTimelineRowSelection = (nodePathInfo) => {
|
|
|
133
387
|
};
|
|
134
388
|
exports.useTimelineRowSelection = useTimelineRowSelection;
|
|
135
389
|
const useTimelineKeyframeSelection = (nodePathInfo, frame) => {
|
|
136
|
-
const { canSelect, isSelected, selectItem } = (0, exports.useTimelineSelection)();
|
|
390
|
+
const { canSelect, isSelected, selectItem, registerSelectableItem } = (0, exports.useTimelineSelection)();
|
|
137
391
|
const selectionItem = (0, react_1.useMemo)(() => ({
|
|
138
392
|
type: 'keyframe',
|
|
139
393
|
nodePathInfo,
|
|
140
394
|
frame,
|
|
141
395
|
}), [nodePathInfo, frame]);
|
|
396
|
+
(0, react_1.useEffect)(() => {
|
|
397
|
+
return registerSelectableItem(selectionItem);
|
|
398
|
+
}, [registerSelectableItem, selectionItem]);
|
|
142
399
|
const selected = isSelected(selectionItem);
|
|
143
|
-
const onSelect = (0, react_1.useCallback)(() => {
|
|
144
|
-
selectItem(selectionItem);
|
|
400
|
+
const onSelect = (0, react_1.useCallback)((interaction) => {
|
|
401
|
+
selectItem(selectionItem, interaction);
|
|
145
402
|
}, [selectItem, selectionItem]);
|
|
146
403
|
return {
|
|
147
404
|
onSelect,
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { TSequence } from 'remotion';
|
|
3
|
+
import type { SequenceNodePathInfo } from '../../helpers/get-timeline-sequence-sort-key';
|
|
3
4
|
export declare const TimelineSequence: React.NamedExoticComponent<{
|
|
4
5
|
readonly s: TSequence;
|
|
6
|
+
readonly nodePathInfo: SequenceNodePathInfo | null;
|
|
5
7
|
}>;
|
|
@@ -44,21 +44,32 @@ const use_max_media_duration_1 = require("../../helpers/use-max-media-duration")
|
|
|
44
44
|
const AudioWaveform_1 = require("../AudioWaveform");
|
|
45
45
|
const LoopedTimelineIndicators_1 = require("./LoopedTimelineIndicators");
|
|
46
46
|
const TimelineImageInfo_1 = require("./TimelineImageInfo");
|
|
47
|
+
const TimelineSelection_1 = require("./TimelineSelection");
|
|
47
48
|
const TimelineSequenceFrame_1 = require("./TimelineSequenceFrame");
|
|
48
49
|
const TimelineVideoInfo_1 = require("./TimelineVideoInfo");
|
|
49
50
|
const TimelineWidthProvider_1 = require("./TimelineWidthProvider");
|
|
50
51
|
const AUDIO_GRADIENT = 'linear-gradient(rgb(16 171 58), rgb(43 165 63) 60%)';
|
|
51
52
|
const VIDEO_GRADIENT = 'linear-gradient(to top, #8e44ad, #9b59b6)';
|
|
52
53
|
const IMAGE_GRADIENT = 'linear-gradient(to top, #2980b9, #3498db)';
|
|
53
|
-
const TimelineSequenceFn = ({ s }) => {
|
|
54
|
+
const TimelineSequenceFn = ({ s, nodePathInfo }) => {
|
|
54
55
|
const windowWidth = (0, react_1.useContext)(TimelineWidthProvider_1.TimelineWidthContext);
|
|
55
56
|
if (windowWidth === null) {
|
|
56
57
|
return null;
|
|
57
58
|
}
|
|
58
|
-
return jsx_runtime_1.jsx(TimelineSequenceInner, { windowWidth: windowWidth, s: s });
|
|
59
|
+
return (jsx_runtime_1.jsx(TimelineSequenceInner, { windowWidth: windowWidth, s: s, nodePathInfo: nodePathInfo }));
|
|
59
60
|
};
|
|
60
|
-
const TimelineSequenceCurrentFrame = ({ s, displayDurationInFrames, premountWidth, postmountWidth, style, children, }) => {
|
|
61
|
+
const TimelineSequenceCurrentFrame = ({ s, displayDurationInFrames, premountWidth, postmountWidth, style, children, nodePathInfo, }) => {
|
|
61
62
|
var _a, _b;
|
|
63
|
+
const { onSelect, selectable } = (0, TimelineSelection_1.useTimelineRowSelection)(nodePathInfo);
|
|
64
|
+
const onPointerDown = (0, react_1.useCallback)((e) => {
|
|
65
|
+
if (e.button === 0) {
|
|
66
|
+
e.stopPropagation();
|
|
67
|
+
onSelect({
|
|
68
|
+
shiftKey: e.shiftKey,
|
|
69
|
+
toggleKey: e.metaKey || e.ctrlKey,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}, [onSelect]);
|
|
62
73
|
const frame = (0, remotion_1.useCurrentFrame)();
|
|
63
74
|
const relativeFrame = frame - s.from;
|
|
64
75
|
const relativeFrameWithPremount = relativeFrame + ((_a = s.premountDisplay) !== null && _a !== void 0 ? _a : 0);
|
|
@@ -75,9 +86,10 @@ const TimelineSequenceCurrentFrame = ({ s, displayDurationInFrames, premountWidt
|
|
|
75
86
|
return {
|
|
76
87
|
...style,
|
|
77
88
|
opacity: isInRange ? 1 : 0.5,
|
|
89
|
+
...(TimelineSelection_1.TIMELINE_TOP_DRAG ? { cursor: 'pointer' } : {}),
|
|
78
90
|
};
|
|
79
91
|
}, [isInRange, style]);
|
|
80
|
-
return (jsx_runtime_1.jsxs("div", { style: actualStyle, title: s.displayName, children: [premountWidth ? (jsx_runtime_1.jsx("div", { style: {
|
|
92
|
+
return (jsx_runtime_1.jsxs("div", { style: actualStyle, title: s.displayName, onPointerDown: selectable ? onPointerDown : undefined, children: [premountWidth ? (jsx_runtime_1.jsx("div", { style: {
|
|
81
93
|
width: premountWidth,
|
|
82
94
|
height: '100%',
|
|
83
95
|
background: `repeating-linear-gradient(
|
|
@@ -111,7 +123,7 @@ const TimelineSequenceCurrentFrame = ({ s, displayDurationInFrames, premountWidt
|
|
|
111
123
|
alignItems: 'center',
|
|
112
124
|
}, children: jsx_runtime_1.jsx(TimelineSequenceFrame_1.TimelineSequenceFrame, { premounted: isPremounting, postmounted: isPostmounting ? s.duration - 1 : null, roundedFrame: roundedFrame }) })) : null] }));
|
|
113
125
|
};
|
|
114
|
-
const TimelineSequenceInner = ({ s, windowWidth }) => {
|
|
126
|
+
const TimelineSequenceInner = ({ s, windowWidth, nodePathInfo }) => {
|
|
115
127
|
// If a duration is 1, it is essentially a still and it should have width 0
|
|
116
128
|
// Some compositions may not be longer than their media duration,
|
|
117
129
|
// if that is the case, it needs to be asynchronously determined
|
|
@@ -165,6 +177,6 @@ const TimelineSequenceInner = ({ s, windowWidth }) => {
|
|
|
165
177
|
if (maxMediaDuration === null && !s.loopDisplay) {
|
|
166
178
|
return null;
|
|
167
179
|
}
|
|
168
|
-
return (jsx_runtime_1.jsxs(TimelineSequenceCurrentFrame, { s: s, displayDurationInFrames: displayDurationInFrames, premountWidth: premountWidth, postmountWidth: postmountWidth, style: style, 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 }))] }));
|
|
180
|
+
return (jsx_runtime_1.jsxs(TimelineSequenceCurrentFrame, { s: s, displayDurationInFrames: displayDurationInFrames, premountWidth: premountWidth, postmountWidth: postmountWidth, style: style, nodePathInfo: nodePathInfo, 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 }))] }));
|
|
169
181
|
};
|
|
170
182
|
exports.TimelineSequence = react_1.default.memo(TimelineSequenceFn);
|
|
@@ -8,6 +8,7 @@ const relativeFrameStyle = {
|
|
|
8
8
|
color: 'white',
|
|
9
9
|
opacity: 0.5,
|
|
10
10
|
whiteSpace: 'nowrap',
|
|
11
|
+
pointerEvents: 'none',
|
|
11
12
|
};
|
|
12
13
|
const TimelineSequenceFrame = ({ roundedFrame, premounted, postmounted }) => {
|
|
13
14
|
return (jsx_runtime_1.jsx("div", { style: relativeFrameStyle, children: premounted
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { TSequence } from 'remotion';
|
|
3
3
|
import type { SequenceNodePathInfo } from '../../helpers/get-timeline-sequence-sort-key';
|
|
4
|
-
export declare const
|
|
4
|
+
export declare const TimelineSequenceItem: React.FC<{
|
|
5
5
|
readonly sequence: TSequence;
|
|
6
6
|
readonly nestedDepth: number;
|
|
7
7
|
readonly nodePathInfo: SequenceNodePathInfo | null;
|
|
8
|
+
readonly keyframeDisplayOffset: number;
|
|
8
9
|
}>;
|