@remotion/studio 4.0.470 → 4.0.472
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/components/AssetSelector.js +10 -1
- package/dist/components/Canvas.js +98 -0
- package/dist/components/CompositionSelectorItem.d.ts +1 -0
- package/dist/components/CompositionSelectorItem.js +12 -4
- package/dist/components/ContextMenu.d.ts +7 -2
- package/dist/components/ContextMenu.js +91 -43
- package/dist/components/Editor.js +14 -6
- package/dist/components/Modals.js +3 -1
- package/dist/components/NewComposition/CodemodFooter.js +2 -2
- package/dist/components/NewComposition/DeleteFolder.d.ts +6 -0
- package/dist/components/NewComposition/DeleteFolder.js +39 -0
- package/dist/components/NewComposition/RenameFolder.d.ts +6 -0
- package/dist/components/NewComposition/RenameFolder.js +60 -0
- package/dist/components/Preview.js +2 -1
- package/dist/components/SelectedOutlineOverlay.d.ts +109 -1
- package/dist/components/SelectedOutlineOverlay.js +489 -73
- package/dist/components/Splitter/SplitterContainer.js +9 -0
- package/dist/components/Splitter/SplitterHandle.js +63 -70
- package/dist/components/Timeline/Timeline.js +121 -1
- package/dist/components/Timeline/TimelineArrayField.d.ts +9 -0
- package/dist/components/Timeline/TimelineArrayField.js +210 -0
- package/dist/components/Timeline/TimelineBooleanField.d.ts +2 -2
- package/dist/components/Timeline/TimelineBooleanField.js +2 -2
- package/dist/components/Timeline/TimelineClipboardKeybindings.d.ts +20 -0
- package/dist/components/Timeline/TimelineClipboardKeybindings.js +265 -0
- package/dist/components/Timeline/TimelineColorField.d.ts +2 -2
- package/dist/components/Timeline/TimelineColorField.js +2 -8
- package/dist/components/Timeline/TimelineDeleteKeybindings.js +15 -0
- package/dist/components/Timeline/TimelineDragHandler.js +1 -0
- package/dist/components/Timeline/TimelineEffectItem.js +159 -6
- package/dist/components/Timeline/TimelineEffectPropItem.js +95 -25
- package/dist/components/Timeline/TimelineEnumField.d.ts +2 -2
- package/dist/components/Timeline/TimelineEnumField.js +3 -3
- package/dist/components/Timeline/TimelineKeyframeControls.d.ts +4 -3
- package/dist/components/Timeline/TimelineKeyframeControls.js +52 -33
- package/dist/components/Timeline/TimelineKeyframedValue.d.ts +7 -2
- package/dist/components/Timeline/TimelineKeyframedValue.js +22 -8
- package/dist/components/Timeline/TimelineLayerEye.d.ts +1 -0
- package/dist/components/Timeline/TimelineLayerEye.js +8 -3
- package/dist/components/Timeline/TimelineNumberField.d.ts +2 -2
- package/dist/components/Timeline/TimelineNumberField.js +7 -11
- package/dist/components/Timeline/TimelinePrimitiveFieldValue.d.ts +17 -0
- package/dist/components/Timeline/TimelinePrimitiveFieldValue.js +53 -0
- package/dist/components/Timeline/TimelineRotationField.d.ts +2 -2
- package/dist/components/Timeline/TimelineRotationField.js +41 -24
- package/dist/components/Timeline/TimelineRowChrome.d.ts +3 -0
- package/dist/components/Timeline/TimelineRowChrome.js +11 -10
- package/dist/components/Timeline/TimelineScaleField.d.ts +20 -0
- package/dist/components/Timeline/TimelineScaleField.js +314 -0
- package/dist/components/Timeline/TimelineSchemaField.d.ts +3 -2
- package/dist/components/Timeline/TimelineSchemaField.js +8 -42
- package/dist/components/Timeline/TimelineSelection.js +3 -2
- package/dist/components/Timeline/TimelineSequence.d.ts +1 -0
- package/dist/components/Timeline/TimelineSequence.js +51 -10
- package/dist/components/Timeline/TimelineSequenceFrame.js +1 -0
- package/dist/components/Timeline/TimelineSequenceItem.js +97 -7
- package/dist/components/Timeline/TimelineSequencePropItem.js +82 -21
- package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.d.ts +58 -0
- package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +528 -0
- package/dist/components/Timeline/TimelineTrack.js +1 -1
- package/dist/components/Timeline/TimelineTranslateField.d.ts +2 -2
- package/dist/components/Timeline/TimelineTranslateField.js +21 -25
- package/dist/components/Timeline/TimelineUvCoordinateField.d.ts +2 -2
- package/dist/components/Timeline/TimelineUvCoordinateField.js +20 -26
- package/dist/components/Timeline/call-add-keyframe.js +2 -0
- package/dist/components/Timeline/call-delete-keyframe.d.ts +16 -0
- package/dist/components/Timeline/call-delete-keyframe.js +86 -14
- package/dist/components/Timeline/delete-selected-keyframe.d.ts +10 -0
- package/dist/components/Timeline/delete-selected-keyframe.js +48 -7
- package/dist/components/Timeline/delete-selected-timeline-item.js +6 -11
- package/dist/components/Timeline/get-node-keyframes.d.ts +5 -2
- package/dist/components/Timeline/get-node-keyframes.js +38 -5
- package/dist/components/Timeline/get-timeline-keyframes.js +4 -4
- package/dist/components/Timeline/reset-selected-timeline-props.d.ts +38 -0
- package/dist/components/Timeline/reset-selected-timeline-props.js +156 -0
- 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-field-utils.d.ts +1 -0
- package/dist/components/Timeline/timeline-field-utils.js +5 -1
- package/dist/components/Timeline/timeline-scroll-logic.js +3 -3
- package/dist/components/Timeline/timeline-translate-utils.js +6 -2
- package/dist/components/Timeline/use-expanded-track-keyframe-rows.js +7 -0
- package/dist/components/Timeline/use-sequence-props-subscription.js +2 -1
- package/dist/components/TopPanel.d.ts +1 -1
- package/dist/components/folder-menu-items.d.ts +12 -0
- package/dist/components/folder-menu-items.js +147 -0
- package/dist/components/import-assets.d.ts +6 -0
- package/dist/components/import-assets.js +157 -0
- package/dist/esm/{chunk-dny42qnq.js → chunk-48grt472.js} +9717 -5925
- package/dist/esm/internals.mjs +9717 -5925
- package/dist/esm/previewEntry.mjs +9531 -5737
- package/dist/esm/renderEntry.mjs +1 -1
- package/dist/helpers/calculate-timeline.js +7 -3
- package/dist/helpers/create-folder-tree.js +1 -0
- package/dist/helpers/detect-file-type.d.ts +69 -0
- package/dist/helpers/detect-file-type.js +278 -0
- package/dist/helpers/get-folder-id.d.ts +4 -0
- package/dist/helpers/get-folder-id.js +7 -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/get-timeline-sequence-sort-key.d.ts +2 -0
- package/dist/helpers/open-in-editor.d.ts +19 -1
- package/dist/helpers/open-in-editor.js +42 -4
- package/dist/helpers/timeline-layout.js +5 -1
- package/dist/helpers/use-menu-structure.js +0 -1
- package/dist/helpers/validate-folder-rename.d.ts +6 -0
- package/dist/helpers/validate-folder-rename.js +19 -0
- package/dist/state/modals.d.ts +10 -0
- package/dist/state/scale-lock.d.ts +18 -0
- package/dist/state/scale-lock.js +59 -0
- package/dist/state/z-index.js +5 -2
- package/package.json +10 -10
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TimelineClipboardKeybindings = exports.getSnapshotsFromSelection = exports.getPasteEffectsTarget = void 0;
|
|
4
|
+
const studio_shared_1 = require("@remotion/studio-shared");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const remotion_1 = require("remotion");
|
|
7
|
+
const client_id_1 = require("../../helpers/client-id");
|
|
8
|
+
const use_keybinding_1 = require("../../helpers/use-keybinding");
|
|
9
|
+
const call_api_1 = require("../call-api");
|
|
10
|
+
const NotificationCenter_1 = require("../Notifications/NotificationCenter");
|
|
11
|
+
const TimelineSelection_1 = require("./TimelineSelection");
|
|
12
|
+
const makeClipboardText = (payload) => JSON.stringify(payload);
|
|
13
|
+
const makeTargetKey = (nodePath) => {
|
|
14
|
+
return JSON.stringify({
|
|
15
|
+
absolutePath: nodePath.absolutePath,
|
|
16
|
+
nodePath: nodePath.nodePath,
|
|
17
|
+
sequenceKeys: nodePath.sequenceKeys,
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
const getTargetSequenceNodePathInfo = (selection) => {
|
|
21
|
+
if (selection.type === 'sequence' ||
|
|
22
|
+
selection.type === 'sequence-effect' ||
|
|
23
|
+
selection.type === 'sequence-all-effects') {
|
|
24
|
+
return selection.nodePathInfo;
|
|
25
|
+
}
|
|
26
|
+
return null;
|
|
27
|
+
};
|
|
28
|
+
const getCopyType = (selection) => {
|
|
29
|
+
if (selection.type === 'sequence-effect') {
|
|
30
|
+
return 'effects-additive';
|
|
31
|
+
}
|
|
32
|
+
if (selection.type === 'sequence-all-effects') {
|
|
33
|
+
return 'effects-replacing';
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
};
|
|
37
|
+
const getPasteEffectsTarget = (selectedItems) => {
|
|
38
|
+
const targetNodePathInfos = selectedItems
|
|
39
|
+
.map(getTargetSequenceNodePathInfo)
|
|
40
|
+
.filter((targetNodePathInfo) => targetNodePathInfo !== null);
|
|
41
|
+
const uniqueTargetKeys = new Set(targetNodePathInfos.map((targetNodePathInfo) => makeTargetKey(targetNodePathInfo.sequenceSubscriptionKey)));
|
|
42
|
+
if (uniqueTargetKeys.size === 0) {
|
|
43
|
+
return { type: 'none' };
|
|
44
|
+
}
|
|
45
|
+
if (uniqueTargetKeys.size !== 1) {
|
|
46
|
+
return { type: 'multiple' };
|
|
47
|
+
}
|
|
48
|
+
const [nodePathInfo] = targetNodePathInfos;
|
|
49
|
+
if (!nodePathInfo) {
|
|
50
|
+
return { type: 'none' };
|
|
51
|
+
}
|
|
52
|
+
if (!nodePathInfo.supportsEffects) {
|
|
53
|
+
return { type: 'unsupported' };
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
type: 'valid',
|
|
57
|
+
nodePathInfo,
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
exports.getPasteEffectsTarget = getPasteEffectsTarget;
|
|
61
|
+
const isClipboardInterpolationFunction = (value) => {
|
|
62
|
+
return (0, studio_shared_1.isKeyframeInterpolationFunction)(value);
|
|
63
|
+
};
|
|
64
|
+
const effectStatusToSnapshot = (effect) => {
|
|
65
|
+
if (effect.importPath === null) {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
const params = {};
|
|
69
|
+
for (const [key, prop] of Object.entries(effect.props)) {
|
|
70
|
+
if (prop.status === 'computed') {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
if (prop.status === 'static') {
|
|
74
|
+
if (prop.codeValue !== undefined) {
|
|
75
|
+
params[key] = {
|
|
76
|
+
type: 'static',
|
|
77
|
+
value: prop.codeValue,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
if (!isClipboardInterpolationFunction(prop.interpolationFunction)) {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
params[key] = {
|
|
86
|
+
type: 'keyframed',
|
|
87
|
+
interpolationFunction: prop.interpolationFunction,
|
|
88
|
+
keyframes: prop.keyframes,
|
|
89
|
+
easing: prop.easing,
|
|
90
|
+
clamping: prop.clamping,
|
|
91
|
+
...(prop.posterize === undefined ? {} : { posterize: prop.posterize }),
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
callee: effect.callee,
|
|
96
|
+
importPath: effect.importPath,
|
|
97
|
+
params,
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
const getSnapshotsFromSelection = ({ selection, codeValues, }) => {
|
|
101
|
+
if (selection.type !== 'sequence-effect' &&
|
|
102
|
+
selection.type !== 'sequence-all-effects') {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
const { sequenceSubscriptionKey } = selection.nodePathInfo;
|
|
106
|
+
const sequenceStatus = codeValues[remotion_1.Internals.makeSequencePropsSubscriptionKey(sequenceSubscriptionKey)];
|
|
107
|
+
if (!sequenceStatus || !sequenceStatus.canUpdate) {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
const effects = selection.type === 'sequence-effect'
|
|
111
|
+
? sequenceStatus.effects.filter((effect) => effect.effectIndex === selection.i)
|
|
112
|
+
: sequenceStatus.effects;
|
|
113
|
+
if (selection.type === 'sequence-effect' && effects.length !== 1) {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
const snapshots = [];
|
|
117
|
+
for (const effect of effects) {
|
|
118
|
+
if (!effect.canUpdate) {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
const snapshot = effectStatusToSnapshot(effect);
|
|
122
|
+
if (snapshot === null) {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
snapshots.push(snapshot);
|
|
126
|
+
}
|
|
127
|
+
return snapshots;
|
|
128
|
+
};
|
|
129
|
+
exports.getSnapshotsFromSelection = getSnapshotsFromSelection;
|
|
130
|
+
const TimelineClipboardKeybindings = () => {
|
|
131
|
+
const keybindings = (0, use_keybinding_1.useKeybinding)();
|
|
132
|
+
const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
|
|
133
|
+
const { canSelect } = (0, TimelineSelection_1.useTimelineSelection)();
|
|
134
|
+
const currentSelection = (0, TimelineSelection_1.useCurrentTimelineSelectionStateAsRef)();
|
|
135
|
+
const { codeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeCodeValuesContext);
|
|
136
|
+
(0, react_1.useEffect)(() => {
|
|
137
|
+
if (!canSelect || previewServerState.type !== 'connected') {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
const { clientId } = previewServerState;
|
|
141
|
+
const copy = keybindings.registerKeybinding({
|
|
142
|
+
event: 'keydown',
|
|
143
|
+
key: 'c',
|
|
144
|
+
callback: (e) => {
|
|
145
|
+
const { selectedItems } = currentSelection.current;
|
|
146
|
+
if (selectedItems.length === 0) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
const firstSelection = selectedItems[0];
|
|
150
|
+
const type = firstSelection ? getCopyType(firstSelection) : null;
|
|
151
|
+
if (type === null) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
if (selectedItems.some((selection) => getCopyType(selection) !== type)) {
|
|
155
|
+
e.preventDefault();
|
|
156
|
+
(0, NotificationCenter_1.showNotification)('Cannot copy individual effects together with all effects', 3000);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
const snapshots = selectedItems.flatMap((selection) => {
|
|
160
|
+
const itemSnapshots = (0, exports.getSnapshotsFromSelection)({
|
|
161
|
+
selection,
|
|
162
|
+
codeValues,
|
|
163
|
+
});
|
|
164
|
+
return itemSnapshots !== null && itemSnapshots !== void 0 ? itemSnapshots : [null];
|
|
165
|
+
});
|
|
166
|
+
if (snapshots.some((snapshot) => snapshot === null)) {
|
|
167
|
+
e.preventDefault();
|
|
168
|
+
(0, NotificationCenter_1.showNotification)('Cannot copy effects because one of them contains values that cannot be copied', 3000);
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
e.preventDefault();
|
|
172
|
+
navigator.clipboard
|
|
173
|
+
.writeText(makeClipboardText({
|
|
174
|
+
type,
|
|
175
|
+
version: 3,
|
|
176
|
+
remotionClipboard: 'effects',
|
|
177
|
+
effects: snapshots,
|
|
178
|
+
}))
|
|
179
|
+
.then(() => {
|
|
180
|
+
(0, NotificationCenter_1.showNotification)(snapshots.length === 1
|
|
181
|
+
? 'Copied effect to clipboard'
|
|
182
|
+
: 'Copied effects to clipboard', 1000);
|
|
183
|
+
})
|
|
184
|
+
.catch((err) => {
|
|
185
|
+
(0, NotificationCenter_1.showNotification)(`Could not copy effects: ${err.message}`, 2000);
|
|
186
|
+
});
|
|
187
|
+
},
|
|
188
|
+
commandCtrlKey: true,
|
|
189
|
+
preventDefault: false,
|
|
190
|
+
triggerIfInputFieldFocused: false,
|
|
191
|
+
keepRegisteredWhenNotHighestContext: false,
|
|
192
|
+
});
|
|
193
|
+
const paste = keybindings.registerKeybinding({
|
|
194
|
+
event: 'keydown',
|
|
195
|
+
key: 'v',
|
|
196
|
+
callback: (e) => {
|
|
197
|
+
const { selectedItems } = currentSelection.current;
|
|
198
|
+
if (selectedItems.length === 0) {
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
navigator.clipboard
|
|
202
|
+
.readText()
|
|
203
|
+
.then((text) => {
|
|
204
|
+
const result = (0, studio_shared_1.parseEffectClipboardDataResult)(text);
|
|
205
|
+
if (result.status === 'invalid') {
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
e.preventDefault();
|
|
209
|
+
if (result.status === 'unsupported-version') {
|
|
210
|
+
(0, NotificationCenter_1.showNotification)('Cannot paste effects copied from a different Remotion Studio version', 4000);
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
const { data: payload } = result;
|
|
214
|
+
const target = (0, exports.getPasteEffectsTarget)(selectedItems);
|
|
215
|
+
if (target.type === 'multiple') {
|
|
216
|
+
(0, NotificationCenter_1.showNotification)('Select one target sequence to paste effects', 3000);
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
if (target.type === 'none') {
|
|
220
|
+
(0, NotificationCenter_1.showNotification)('Select a sequence to paste effects onto', 3000);
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
if (target.type === 'unsupported') {
|
|
224
|
+
(0, NotificationCenter_1.showNotification)('This sequence does not support effects', 3000);
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
const { sequenceSubscriptionKey: targetSequenceNodePath } = target.nodePathInfo;
|
|
228
|
+
return (0, call_api_1.callApi)('/api/paste-effects', {
|
|
229
|
+
targetFileName: targetSequenceNodePath.absolutePath,
|
|
230
|
+
targetSequenceNodePath,
|
|
231
|
+
type: payload.type,
|
|
232
|
+
effects: payload.effects,
|
|
233
|
+
clientId,
|
|
234
|
+
}).then((pasteResult) => {
|
|
235
|
+
if (pasteResult.success) {
|
|
236
|
+
(0, NotificationCenter_1.showNotification)('Pasted effects', 2000);
|
|
237
|
+
}
|
|
238
|
+
else {
|
|
239
|
+
(0, NotificationCenter_1.showNotification)(pasteResult.reason, 4000);
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
})
|
|
243
|
+
.catch((err) => {
|
|
244
|
+
(0, NotificationCenter_1.showNotification)(`Could not paste effects: ${err.message}`, 3000);
|
|
245
|
+
});
|
|
246
|
+
},
|
|
247
|
+
commandCtrlKey: true,
|
|
248
|
+
preventDefault: false,
|
|
249
|
+
triggerIfInputFieldFocused: false,
|
|
250
|
+
keepRegisteredWhenNotHighestContext: false,
|
|
251
|
+
});
|
|
252
|
+
return () => {
|
|
253
|
+
copy.unregister();
|
|
254
|
+
paste.unregister();
|
|
255
|
+
};
|
|
256
|
+
}, [
|
|
257
|
+
canSelect,
|
|
258
|
+
codeValues,
|
|
259
|
+
currentSelection,
|
|
260
|
+
keybindings,
|
|
261
|
+
previewServerState,
|
|
262
|
+
]);
|
|
263
|
+
return null;
|
|
264
|
+
};
|
|
265
|
+
exports.TimelineClipboardKeybindings = TimelineClipboardKeybindings;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import type {
|
|
2
|
+
import type { CanUpdateSequencePropStatusStatic } from 'remotion';
|
|
3
3
|
import type { SchemaFieldInfo, TimelineFieldOnDragValueChange, TimelineFieldOnSave } from '../../helpers/timeline-layout';
|
|
4
4
|
export declare const TimelineColorField: React.FC<{
|
|
5
5
|
readonly field: SchemaFieldInfo;
|
|
6
6
|
readonly effectiveValue: unknown;
|
|
7
|
-
readonly propStatus:
|
|
7
|
+
readonly propStatus: CanUpdateSequencePropStatusStatic;
|
|
8
8
|
readonly onSave: TimelineFieldOnSave;
|
|
9
9
|
readonly onDragValueChange: TimelineFieldOnDragValueChange;
|
|
10
10
|
readonly onDragEnd: () => void;
|
|
@@ -19,15 +19,9 @@ const TimelineColorField = ({ field, effectiveValue, propStatus, onSave, onDragV
|
|
|
19
19
|
? ((_a = field.fieldSchema.default) !== null && _a !== void 0 ? _a : '#000')
|
|
20
20
|
: '';
|
|
21
21
|
const onChange = (0, react_1.useCallback)((next) => {
|
|
22
|
-
if (!propStatus.canUpdate) {
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
22
|
onDragValueChange(next);
|
|
26
|
-
}, [onDragValueChange
|
|
23
|
+
}, [onDragValueChange]);
|
|
27
24
|
const onChangeComplete = (0, react_1.useCallback)((next) => {
|
|
28
|
-
if (!propStatus.canUpdate) {
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
25
|
if (next !== propStatus.codeValue) {
|
|
32
26
|
onSave(next);
|
|
33
27
|
}
|
|
@@ -38,6 +32,6 @@ const TimelineColorField = ({ field, effectiveValue, propStatus, onSave, onDragV
|
|
|
38
32
|
marginLeft: 5,
|
|
39
33
|
};
|
|
40
34
|
}, []);
|
|
41
|
-
return (jsx_runtime_1.jsx("span", { style: containerStyle, children: jsx_runtime_1.jsx(ColorPicker_1.ColorPicker, { value: currentValue, status: "ok", onChange: onChange, onChangeComplete: onChangeComplete, width: SWATCH_WIDTH, height: SWATCH_HEIGHT, disabled:
|
|
35
|
+
return (jsx_runtime_1.jsx("span", { style: containerStyle, children: jsx_runtime_1.jsx(ColorPicker_1.ColorPicker, { value: currentValue, status: "ok", onChange: onChange, onChangeComplete: onChangeComplete, width: SWATCH_WIDTH, height: SWATCH_HEIGHT, disabled: false, name: field.key, title: currentValue, style: swatchStyle }) }));
|
|
42
36
|
};
|
|
43
37
|
exports.TimelineColorField = TimelineColorField;
|
|
@@ -7,12 +7,14 @@ const client_id_1 = require("../../helpers/client-id");
|
|
|
7
7
|
const use_keybinding_1 = require("../../helpers/use-keybinding");
|
|
8
8
|
const delete_selected_timeline_item_1 = require("./delete-selected-timeline-item");
|
|
9
9
|
const duplicate_selected_timeline_item_1 = require("./duplicate-selected-timeline-item");
|
|
10
|
+
const reset_selected_timeline_props_1 = require("./reset-selected-timeline-props");
|
|
10
11
|
const TimelineSelection_1 = require("./TimelineSelection");
|
|
11
12
|
const TimelineDeleteKeybindings = () => {
|
|
12
13
|
const keybindings = (0, use_keybinding_1.useKeybinding)();
|
|
13
14
|
const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
|
|
14
15
|
const { sequences } = (0, react_1.useContext)(remotion_1.Internals.SequenceManager);
|
|
15
16
|
const { overrideIdToNodePathMappings } = (0, react_1.useContext)(remotion_1.Internals.OverrideIdsToNodePathsGettersContext);
|
|
17
|
+
const { codeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeCodeValuesContext);
|
|
16
18
|
const { setCodeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
|
|
17
19
|
const { canSelect } = (0, TimelineSelection_1.useTimelineSelection)();
|
|
18
20
|
const currentSelection = (0, TimelineSelection_1.useCurrentTimelineSelectionStateAsRef)();
|
|
@@ -29,6 +31,18 @@ const TimelineDeleteKeybindings = () => {
|
|
|
29
31
|
if (selectedItems.length === 0) {
|
|
30
32
|
return;
|
|
31
33
|
}
|
|
34
|
+
const resetPromise = (0, reset_selected_timeline_props_1.resetSelectedTimelineProps)({
|
|
35
|
+
selections: selectedItems,
|
|
36
|
+
sequences,
|
|
37
|
+
overrideIdsToNodePaths: overrideIdToNodePathMappings,
|
|
38
|
+
codeValues,
|
|
39
|
+
setCodeValues,
|
|
40
|
+
clientId,
|
|
41
|
+
});
|
|
42
|
+
if (resetPromise !== null) {
|
|
43
|
+
resetPromise.catch(() => undefined);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
32
46
|
const deletePromise = (0, delete_selected_timeline_item_1.deleteSelectedTimelineItems)({
|
|
33
47
|
selections: selectedItems,
|
|
34
48
|
sequences,
|
|
@@ -74,6 +88,7 @@ const TimelineDeleteKeybindings = () => {
|
|
|
74
88
|
};
|
|
75
89
|
}, [
|
|
76
90
|
canSelect,
|
|
91
|
+
codeValues,
|
|
77
92
|
currentSelection,
|
|
78
93
|
keybindings,
|
|
79
94
|
overrideIdToNodePathMappings,
|
|
@@ -125,6 +125,7 @@ const TimelineDragHandlerInner = () => {
|
|
|
125
125
|
if (!videoConfig) {
|
|
126
126
|
return;
|
|
127
127
|
}
|
|
128
|
+
e.stopPropagation();
|
|
128
129
|
document.body.style.userSelect = 'none';
|
|
129
130
|
document.body.style.webkitUserSelect = 'none';
|
|
130
131
|
const frame = (0, timeline_scroll_logic_1.getFrameFromX)({
|
|
@@ -14,11 +14,55 @@ const TimelineExpandArrowButton_1 = require("./TimelineExpandArrowButton");
|
|
|
14
14
|
const TimelineLayerEye_1 = require("./TimelineLayerEye");
|
|
15
15
|
const TimelineRowChrome_1 = require("./TimelineRowChrome");
|
|
16
16
|
const TimelineSelection_1 = require("./TimelineSelection");
|
|
17
|
+
const EFFECT_REORDER_MIME_TYPE = 'application/remotion-effect-reorder';
|
|
18
|
+
let currentEffectDrag = null;
|
|
17
19
|
const rowLabel = {
|
|
18
20
|
fontSize: 12,
|
|
19
21
|
color: 'rgba(255, 255, 255, 0.8)',
|
|
20
22
|
userSelect: 'none',
|
|
21
23
|
};
|
|
24
|
+
const rowStyle = {
|
|
25
|
+
height: timeline_layout_1.TREE_GROUP_ROW_HEIGHT,
|
|
26
|
+
cursor: 'default',
|
|
27
|
+
};
|
|
28
|
+
const reorderWrapper = {
|
|
29
|
+
position: 'relative',
|
|
30
|
+
};
|
|
31
|
+
const reorderLineBase = {
|
|
32
|
+
backgroundColor: '#0b84ff',
|
|
33
|
+
height: 2,
|
|
34
|
+
left: 0,
|
|
35
|
+
pointerEvents: 'none',
|
|
36
|
+
position: 'absolute',
|
|
37
|
+
right: 0,
|
|
38
|
+
zIndex: 1,
|
|
39
|
+
};
|
|
40
|
+
const hasEffectReorderDragType = (dataTransfer) => {
|
|
41
|
+
return Array.from(dataTransfer.types).includes(EFFECT_REORDER_MIME_TYPE);
|
|
42
|
+
};
|
|
43
|
+
const getEffectReorderDragData = (dataTransfer) => {
|
|
44
|
+
if (currentEffectDrag) {
|
|
45
|
+
return currentEffectDrag;
|
|
46
|
+
}
|
|
47
|
+
const value = dataTransfer.getData(EFFECT_REORDER_MIME_TYPE);
|
|
48
|
+
if (!value) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
const parsed = JSON.parse(value);
|
|
53
|
+
if (typeof parsed.nodePathKey === 'string' &&
|
|
54
|
+
typeof parsed.effectIndex === 'number') {
|
|
55
|
+
return parsed;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
catch (_a) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
return null;
|
|
62
|
+
};
|
|
63
|
+
const getDestinationIndex = ({ fromIndex, insertionIndex, }) => {
|
|
64
|
+
return insertionIndex > fromIndex ? insertionIndex - 1 : insertionIndex;
|
|
65
|
+
};
|
|
22
66
|
const TimelineEffectItem = ({ label, nodePathInfo, effectIndex, effectSchema, documentationLink, nodePath, validatedLocation, rowDepth, getIsExpanded, toggleTrack, }) => {
|
|
23
67
|
var _a;
|
|
24
68
|
var _b;
|
|
@@ -27,6 +71,7 @@ const TimelineEffectItem = ({ label, nodePathInfo, effectIndex, effectSchema, do
|
|
|
27
71
|
const { codeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeCodeValuesContext);
|
|
28
72
|
const { setCodeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
|
|
29
73
|
const selection = (0, TimelineSelection_1.useTimelineRowSelection)(nodePathInfo);
|
|
74
|
+
const [dropIndicator, setDropIndicator] = (0, react_1.useState)(null);
|
|
30
75
|
const effectStatus = (0, react_1.useMemo)(() => remotion_1.Internals.getEffectCodeValuesCtx({
|
|
31
76
|
codeValues,
|
|
32
77
|
nodePath,
|
|
@@ -36,15 +81,20 @@ const TimelineEffectItem = ({ label, nodePathInfo, effectIndex, effectSchema, do
|
|
|
36
81
|
? ((_b = (_a = effectStatus.props) === null || _a === void 0 ? void 0 : _a.disabled) !== null && _b !== void 0 ? _b : null)
|
|
37
82
|
: null;
|
|
38
83
|
const isDisabled = (0, react_1.useMemo)(() => {
|
|
39
|
-
if (disabledStatus
|
|
84
|
+
if ((disabledStatus === null || disabledStatus === void 0 ? void 0 : disabledStatus.status) === 'static') {
|
|
40
85
|
return Boolean(disabledStatus.codeValue);
|
|
41
86
|
}
|
|
42
87
|
return false;
|
|
43
88
|
}, [disabledStatus]);
|
|
44
|
-
const canToggle = previewConnected && disabledStatus
|
|
89
|
+
const canToggle = previewConnected && (disabledStatus === null || disabledStatus === void 0 ? void 0 : disabledStatus.status) === 'static';
|
|
45
90
|
const deleteDisabled = !previewConnected ||
|
|
46
91
|
effectStatus.type !== 'can-update-effect' ||
|
|
47
92
|
!validatedLocation.source;
|
|
93
|
+
const canReorder = TimelineSelection_1.SELECTION_ENABLED &&
|
|
94
|
+
previewConnected &&
|
|
95
|
+
effectStatus.type === 'can-update-effect' &&
|
|
96
|
+
Boolean(validatedLocation.source);
|
|
97
|
+
const nodePathKey = (0, react_1.useMemo)(() => remotion_1.Internals.makeSequencePropsSubscriptionKey(nodePath), [nodePath]);
|
|
48
98
|
const onDeleteEffectFromSource = (0, react_1.useCallback)(async () => {
|
|
49
99
|
if (deleteDisabled) {
|
|
50
100
|
return;
|
|
@@ -148,9 +198,6 @@ const TimelineEffectItem = ({ label, nodePathInfo, effectIndex, effectSchema, do
|
|
|
148
198
|
validatedLocation.source,
|
|
149
199
|
]);
|
|
150
200
|
const isExpanded = getIsExpanded(nodePathInfo);
|
|
151
|
-
const rowStyle = (0, react_1.useMemo)(() => ({
|
|
152
|
-
height: timeline_layout_1.TREE_GROUP_ROW_HEIGHT,
|
|
153
|
-
}), []);
|
|
154
201
|
const labelStyle = (0, react_1.useMemo)(() => {
|
|
155
202
|
return {
|
|
156
203
|
...rowLabel,
|
|
@@ -164,7 +211,113 @@ const TimelineEffectItem = ({ label, nodePathInfo, effectIndex, effectSchema, do
|
|
|
164
211
|
paddingRight: timeline_layout_1.EXPANDED_SECTION_PADDING_RIGHT,
|
|
165
212
|
};
|
|
166
213
|
}, [selection.selected]);
|
|
214
|
+
const getDropTarget = (0, react_1.useCallback)((e) => {
|
|
215
|
+
const dragData = getEffectReorderDragData(e.dataTransfer);
|
|
216
|
+
if (!dragData || dragData.nodePathKey !== nodePathKey) {
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
const rect = e.currentTarget.getBoundingClientRect();
|
|
220
|
+
const before = e.clientY < rect.top + rect.height / 2;
|
|
221
|
+
const insertionIndex = before ? effectIndex : effectIndex + 1;
|
|
222
|
+
const toIndex = getDestinationIndex({
|
|
223
|
+
fromIndex: dragData.effectIndex,
|
|
224
|
+
insertionIndex,
|
|
225
|
+
});
|
|
226
|
+
if (toIndex === dragData.effectIndex) {
|
|
227
|
+
return null;
|
|
228
|
+
}
|
|
229
|
+
return {
|
|
230
|
+
dragData,
|
|
231
|
+
toIndex,
|
|
232
|
+
indicator: before ? 'before' : 'after',
|
|
233
|
+
};
|
|
234
|
+
}, [effectIndex, nodePathKey]);
|
|
235
|
+
const onDragStart = (0, react_1.useCallback)((e) => {
|
|
236
|
+
if (!canReorder) {
|
|
237
|
+
e.preventDefault();
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
const dragData = { nodePathKey, effectIndex };
|
|
241
|
+
currentEffectDrag = dragData;
|
|
242
|
+
e.dataTransfer.effectAllowed = 'move';
|
|
243
|
+
e.dataTransfer.setData(EFFECT_REORDER_MIME_TYPE, JSON.stringify(dragData));
|
|
244
|
+
e.stopPropagation();
|
|
245
|
+
}, [canReorder, effectIndex, nodePathKey]);
|
|
246
|
+
const onDragEnd = (0, react_1.useCallback)(() => {
|
|
247
|
+
currentEffectDrag = null;
|
|
248
|
+
setDropIndicator(null);
|
|
249
|
+
}, []);
|
|
250
|
+
const onDragOver = (0, react_1.useCallback)((e) => {
|
|
251
|
+
if (!canReorder || !hasEffectReorderDragType(e.dataTransfer)) {
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
const dropTarget = getDropTarget(e);
|
|
255
|
+
if (!dropTarget) {
|
|
256
|
+
setDropIndicator(null);
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
e.preventDefault();
|
|
260
|
+
e.stopPropagation();
|
|
261
|
+
e.dataTransfer.dropEffect = 'move';
|
|
262
|
+
setDropIndicator(dropTarget.indicator);
|
|
263
|
+
}, [canReorder, getDropTarget]);
|
|
264
|
+
const onDragLeave = (0, react_1.useCallback)((e) => {
|
|
265
|
+
if (e.currentTarget.contains(e.relatedTarget)) {
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
setDropIndicator(null);
|
|
269
|
+
}, []);
|
|
270
|
+
const onDrop = (0, react_1.useCallback)(async (e) => {
|
|
271
|
+
if (!canReorder ||
|
|
272
|
+
previewServerState.type !== 'connected' ||
|
|
273
|
+
!validatedLocation.source) {
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
const dropTarget = getDropTarget(e);
|
|
277
|
+
if (!dropTarget) {
|
|
278
|
+
setDropIndicator(null);
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
e.preventDefault();
|
|
282
|
+
e.stopPropagation();
|
|
283
|
+
setDropIndicator(null);
|
|
284
|
+
currentEffectDrag = null;
|
|
285
|
+
try {
|
|
286
|
+
const result = await (0, call_api_1.callApi)('/api/reorder-effect', {
|
|
287
|
+
fileName: validatedLocation.source,
|
|
288
|
+
sequenceNodePath: nodePath,
|
|
289
|
+
fromIndex: dropTarget.dragData.effectIndex,
|
|
290
|
+
toIndex: dropTarget.toIndex,
|
|
291
|
+
clientId: previewServerState.clientId,
|
|
292
|
+
});
|
|
293
|
+
if (result.success) {
|
|
294
|
+
(0, NotificationCenter_1.showNotification)('Reordered effect', 2000);
|
|
295
|
+
}
|
|
296
|
+
else {
|
|
297
|
+
(0, NotificationCenter_1.showNotification)(result.reason, 4000);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
catch (err) {
|
|
301
|
+
(0, NotificationCenter_1.showNotification)(err.message, 4000);
|
|
302
|
+
}
|
|
303
|
+
}, [
|
|
304
|
+
canReorder,
|
|
305
|
+
getDropTarget,
|
|
306
|
+
nodePath,
|
|
307
|
+
previewServerState,
|
|
308
|
+
validatedLocation.source,
|
|
309
|
+
]);
|
|
310
|
+
const reorderLineStyle = (0, react_1.useMemo)(() => {
|
|
311
|
+
if (!dropIndicator) {
|
|
312
|
+
return null;
|
|
313
|
+
}
|
|
314
|
+
return {
|
|
315
|
+
...reorderLineBase,
|
|
316
|
+
...(dropIndicator === 'before' ? { top: -1 } : { bottom: -1 }),
|
|
317
|
+
};
|
|
318
|
+
}, [dropIndicator]);
|
|
167
319
|
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 }) }));
|
|
168
|
-
|
|
320
|
+
const draggableRow = canReorder ? (jsx_runtime_1.jsxs("div", { draggable: true, onDragStart: onDragStart, onDragEnd: onDragEnd, onDragOver: onDragOver, onDragLeave: onDragLeave, onDrop: onDrop, style: reorderWrapper, children: [reorderLineStyle ? jsx_runtime_1.jsx("div", { style: reorderLineStyle }) : null, row] })) : (row);
|
|
321
|
+
return previewConnected ? (jsx_runtime_1.jsx(ContextMenu_1.ContextMenu, { values: contextMenuValues, onOpen: selection.selectable ? selection.onSelect : null, children: draggableRow })) : (draggableRow);
|
|
169
322
|
};
|
|
170
323
|
exports.TimelineEffectItem = TimelineEffectItem;
|