@remotion/studio 4.0.496 → 4.0.497
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/AudioWaveform.js +1 -11
- package/dist/components/Canvas.js +22 -203
- package/dist/components/CompositionSelectorItem.js +2 -10
- package/dist/components/InspectorPanel/AlignmentControls.js +2 -0
- package/dist/components/InspectorPanel/ConnectedCompositionsSection.js +27 -2
- package/dist/components/InspectorPanel/SequenceSelectionInspector.js +65 -8
- package/dist/components/InspectorPanel/use-composition-actions.js +6 -2
- package/dist/components/NewComposition/CodemodFooter.d.ts +1 -1
- package/dist/components/NewComposition/CodemodFooter.js +23 -4
- package/dist/components/NewComposition/InputDragger.d.ts +6 -0
- package/dist/components/NewComposition/InputDragger.js +12 -3
- package/dist/components/NewComposition/NewComposition.js +1 -1
- package/dist/components/NewComposition/use-rename-static-file.js +1 -1
- package/dist/components/SelectedOutlineElement.js +56 -88
- package/dist/components/SelectedOutlineOverlay.d.ts +1 -1
- package/dist/components/SelectedOutlineOverlay.js +9 -10
- package/dist/components/Timeline/Timeline.js +10 -3
- package/dist/components/Timeline/TimelineAssetDropIndicator.d.ts +2 -0
- package/dist/components/Timeline/TimelineAssetDropIndicator.js +37 -0
- package/dist/components/Timeline/TimelineClipboardKeybindings.js +1 -7
- package/dist/components/Timeline/TimelineScrollable.js +3 -2
- package/dist/components/Timeline/TimelineSelection.d.ts +4 -0
- package/dist/components/Timeline/TimelineSelection.js +40 -5
- package/dist/components/Timeline/TimelineSequence.js +20 -8
- package/dist/components/Timeline/TimelineSequenceFrame.js +2 -4
- package/dist/components/Timeline/TimelineSequenceItem.js +2 -0
- package/dist/components/Timeline/TimelineSequencePropItem.js +4 -0
- package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.d.ts +15 -3
- package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +96 -18
- package/dist/components/Timeline/TimelineTimeIndicators.d.ts +16 -0
- package/dist/components/Timeline/TimelineTimeIndicators.js +154 -35
- package/dist/components/Timeline/TimelineTranslateField.js +2 -1
- package/dist/components/Timeline/TimelineVideoInfo.d.ts +1 -0
- package/dist/components/Timeline/TimelineVideoInfo.js +4 -1
- package/dist/components/Timeline/delete-selected-timeline-item.d.ts +2 -0
- package/dist/components/Timeline/delete-selected-timeline-item.js +5 -4
- package/dist/components/Timeline/disable-sequence-interactivity.js +2 -0
- package/dist/components/Timeline/get-timeline-media-visualization-layout.d.ts +8 -0
- package/dist/components/Timeline/get-timeline-media-visualization-layout.js +10 -0
- package/dist/components/Timeline/get-timeline-video-info-widths.js +11 -3
- package/dist/components/Timeline/keyframe-clipboard.js +21 -5
- package/dist/components/Timeline/reset-selected-timeline-props.js +2 -0
- package/dist/components/Timeline/save-sequence-prop.d.ts +5 -3
- package/dist/components/Timeline/save-sequence-prop.js +43 -18
- package/dist/components/Timeline/should-clear-selection-on-pointer-down.d.ts +2 -0
- package/dist/components/Timeline/should-clear-selection-on-pointer-down.js +1 -1
- package/dist/components/Timeline/timeline-asset-drop-context.d.ts +1 -0
- package/dist/components/Timeline/timeline-asset-drop-context.js +5 -0
- package/dist/components/Timeline/timeline-scroll-logic.d.ts +7 -0
- package/dist/components/Timeline/timeline-scroll-logic.js +10 -1
- package/dist/components/Timeline/use-rename-sequence.js +2 -0
- package/dist/components/Timeline/use-sequence-freeze-frame-menu-item.js +2 -0
- package/dist/components/Timeline/use-timeline-asset-drop.d.ts +1 -0
- package/dist/components/Timeline/use-timeline-asset-drop.js +168 -0
- package/dist/components/composition-menu-items.d.ts +15 -1
- package/dist/components/composition-menu-items.js +137 -107
- package/dist/components/drop-handler-data.d.ts +13 -0
- package/dist/components/drop-handler-data.js +117 -0
- package/dist/components/handle-drop.d.ts +13 -0
- package/dist/components/handle-drop.js +115 -0
- package/dist/components/import-assets.d.ts +26 -8
- package/dist/components/import-assets.js +161 -49
- package/dist/components/selected-outline-drag.d.ts +11 -1
- package/dist/components/selected-outline-drag.js +74 -1
- package/dist/esm/{chunk-0v4n7nkh.js → chunk-5wj95bdd.js} +4262 -3392
- package/dist/esm/internals.mjs +4262 -3392
- package/dist/esm/previewEntry.mjs +4464 -3594
- package/dist/esm/renderEntry.mjs +1 -1
- package/dist/helpers/is-video-with-last-frame-hold.d.ts +2 -0
- package/dist/helpers/is-video-with-last-frame-hold.js +9 -0
- package/dist/helpers/url-state.d.ts +1 -0
- package/dist/helpers/url-state.js +5 -1
- package/dist/helpers/use-max-media-duration.js +5 -3
- package/dist/helpers/use-menu-structure.js +2 -0
- package/dist/icons/duplicate.d.ts +5 -0
- package/dist/icons/duplicate.js +10 -0
- package/dist/icons/snowflake.d.ts +5 -0
- package/dist/icons/snowflake.js +10 -0
- package/dist/icons/trash.d.ts +5 -0
- package/dist/icons/trash.js +8 -0
- package/package.json +11 -11
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.TimelineTimeIndicators = exports.TimelineTimePadding = exports.TimelineTimePlaceholders = exports.TIMELINE_TIME_INDICATOR_HEIGHT = void 0;
|
|
3
|
+
exports.TimelineTimeIndicators = exports.getTimelineTickScale = exports.getNiceSecondInterval = exports.TimelineTimePadding = exports.TimelineTimePlaceholders = exports.TIMELINE_TIME_INDICATOR_HEIGHT = 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");
|
|
@@ -33,6 +33,10 @@ const secondTick = {
|
|
|
33
33
|
const TICK_LABEL_FONT_SIZE = 12;
|
|
34
34
|
const TICK_LABEL_MARGIN_LEFT = 8;
|
|
35
35
|
const TICK_LABEL_MIN_GAP = 16;
|
|
36
|
+
const MIN_SPACING_BETWEEN_FRAME_TICKS_PX = 5;
|
|
37
|
+
const MIN_SPACING_BETWEEN_TIME_TICKS_PX = 16;
|
|
38
|
+
const MIN_SPACING_BETWEEN_MEDIUM_FRAME_TICKS_PX = 24;
|
|
39
|
+
const MIN_SPACING_BETWEEN_MEDIUM_TIME_TICKS_PX = 48;
|
|
36
40
|
const tickLabel = {
|
|
37
41
|
fontSize: TICK_LABEL_FONT_SIZE,
|
|
38
42
|
marginLeft: TICK_LABEL_MARGIN_LEFT,
|
|
@@ -60,6 +64,101 @@ const TimelineTimePadding = () => {
|
|
|
60
64
|
} }));
|
|
61
65
|
};
|
|
62
66
|
exports.TimelineTimePadding = TimelineTimePadding;
|
|
67
|
+
const NICE_SECOND_INTERVALS = [
|
|
68
|
+
1,
|
|
69
|
+
2,
|
|
70
|
+
5,
|
|
71
|
+
10,
|
|
72
|
+
15,
|
|
73
|
+
30,
|
|
74
|
+
60,
|
|
75
|
+
2 * 60,
|
|
76
|
+
3 * 60,
|
|
77
|
+
5 * 60,
|
|
78
|
+
10 * 60,
|
|
79
|
+
15 * 60,
|
|
80
|
+
20 * 60,
|
|
81
|
+
30 * 60,
|
|
82
|
+
60 * 60,
|
|
83
|
+
];
|
|
84
|
+
const getNiceSecondInterval = (rawNthSecond) => {
|
|
85
|
+
for (const n of NICE_SECOND_INTERVALS) {
|
|
86
|
+
if (n >= rawNthSecond) {
|
|
87
|
+
return n;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return Math.ceil(rawNthSecond / 3600) * 3600;
|
|
91
|
+
};
|
|
92
|
+
exports.getNiceSecondInterval = getNiceSecondInterval;
|
|
93
|
+
const getIntegerDivisors = (value) => {
|
|
94
|
+
const lowerDivisors = [];
|
|
95
|
+
const upperDivisors = [];
|
|
96
|
+
for (let candidate = 1; candidate <= Math.sqrt(value); candidate++) {
|
|
97
|
+
if (value % candidate !== 0) {
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
lowerDivisors.push(candidate);
|
|
101
|
+
if (candidate !== value / candidate) {
|
|
102
|
+
upperDivisors.unshift(value / candidate);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return [...lowerDivisors, ...upperDivisors];
|
|
106
|
+
};
|
|
107
|
+
const getFrameIntervals = (fps) => {
|
|
108
|
+
if (Number.isInteger(fps)) {
|
|
109
|
+
return getIntegerDivisors(fps);
|
|
110
|
+
}
|
|
111
|
+
return [1, 2, 5, 10, 15, 20, 30, 60].filter((interval) => interval < fps);
|
|
112
|
+
};
|
|
113
|
+
const getSecondIntervals = (labelEverySeconds) => {
|
|
114
|
+
const hourlyIntervals = getIntegerDivisors(labelEverySeconds / 3600).map((hours) => hours * 3600);
|
|
115
|
+
return [...new Set([...NICE_SECOND_INTERVALS, ...hourlyIntervals])].sort((a, b) => a - b);
|
|
116
|
+
};
|
|
117
|
+
const getTimelineTickScale = ({ fps, frameInterval, rawSecondMarkerEveryNth, }) => {
|
|
118
|
+
const labelEverySeconds = (0, exports.getNiceSecondInterval)(rawSecondMarkerEveryNth);
|
|
119
|
+
const frameIntervals = getFrameIntervals(fps);
|
|
120
|
+
const rawFrameInterval = MIN_SPACING_BETWEEN_FRAME_TICKS_PX / frameInterval;
|
|
121
|
+
const minorFrameInterval = frameIntervals.find((interval) => interval >= rawFrameInterval && interval < fps);
|
|
122
|
+
if (minorFrameInterval !== undefined) {
|
|
123
|
+
const rawMediumFrameInterval = MIN_SPACING_BETWEEN_MEDIUM_FRAME_TICKS_PX / frameInterval;
|
|
124
|
+
const mediumFrameInterval = frameIntervals.find((interval) => interval >= rawMediumFrameInterval &&
|
|
125
|
+
interval < fps &&
|
|
126
|
+
interval % minorFrameInterval === 0);
|
|
127
|
+
return {
|
|
128
|
+
labelEverySeconds,
|
|
129
|
+
mediumTickEvery: mediumFrameInterval === undefined
|
|
130
|
+
? null
|
|
131
|
+
: { interval: mediumFrameInterval, unit: 'frames' },
|
|
132
|
+
minorTickEvery: { interval: minorFrameInterval, unit: 'frames' },
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
const pixelsPerSecond = frameInterval * fps;
|
|
136
|
+
const secondIntervals = getSecondIntervals(labelEverySeconds);
|
|
137
|
+
const rawMinorSecondInterval = MIN_SPACING_BETWEEN_TIME_TICKS_PX / pixelsPerSecond;
|
|
138
|
+
const minorSecondInterval = secondIntervals.find((interval) => interval >= rawMinorSecondInterval &&
|
|
139
|
+
interval < labelEverySeconds &&
|
|
140
|
+
labelEverySeconds % interval === 0);
|
|
141
|
+
if (minorSecondInterval === undefined) {
|
|
142
|
+
return {
|
|
143
|
+
labelEverySeconds,
|
|
144
|
+
mediumTickEvery: null,
|
|
145
|
+
minorTickEvery: null,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
const rawMediumSecondInterval = MIN_SPACING_BETWEEN_MEDIUM_TIME_TICKS_PX / pixelsPerSecond;
|
|
149
|
+
const mediumSecondInterval = secondIntervals.find((interval) => interval >= rawMediumSecondInterval &&
|
|
150
|
+
interval < labelEverySeconds &&
|
|
151
|
+
interval % minorSecondInterval === 0 &&
|
|
152
|
+
labelEverySeconds % interval === 0);
|
|
153
|
+
return {
|
|
154
|
+
labelEverySeconds,
|
|
155
|
+
mediumTickEvery: mediumSecondInterval === undefined
|
|
156
|
+
? null
|
|
157
|
+
: { interval: mediumSecondInterval, unit: 'seconds' },
|
|
158
|
+
minorTickEvery: { interval: minorSecondInterval, unit: 'seconds' },
|
|
159
|
+
};
|
|
160
|
+
};
|
|
161
|
+
exports.getTimelineTickScale = getTimelineTickScale;
|
|
63
162
|
const TimelineTimeIndicators = () => {
|
|
64
163
|
const sliderTrack = (0, react_1.useContext)(TimelineWidthProvider_1.TimelineWidthContext);
|
|
65
164
|
const video = remotion_1.Internals.useVideo();
|
|
@@ -101,53 +200,73 @@ const TimelineTimeIndicatorsInner = ({ windowWidth, durationInFrames, fps }) =>
|
|
|
101
200
|
}, [windowWidth]);
|
|
102
201
|
const ticks = (0, react_1.useMemo)(() => {
|
|
103
202
|
const frameInterval = (0, timeline_scroll_logic_1.getFrameIncrementFromWidth)(durationInFrames, windowWidth);
|
|
104
|
-
const MIN_SPACING_BETWEEN_TICKS_PX = 5;
|
|
105
203
|
const maxTickLabelWidth = (0, render_frame_1.renderFrame)(durationInFrames - 1, fps).length *
|
|
106
204
|
TICK_LABEL_FONT_SIZE *
|
|
107
205
|
0.6;
|
|
108
206
|
const minSpacingBetweenTickLabelsPx = TICK_LABEL_MARGIN_LEFT + maxTickLabelWidth + TICK_LABEL_MIN_GAP;
|
|
109
207
|
const seconds = Math.floor(durationInFrames / fps);
|
|
110
|
-
const
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
208
|
+
const rawSecondMarkerEveryNth = minSpacingBetweenTickLabelsPx / (frameInterval * fps);
|
|
209
|
+
const tickScale = (0, exports.getTimelineTickScale)({
|
|
210
|
+
fps,
|
|
211
|
+
frameInterval,
|
|
212
|
+
rawSecondMarkerEveryNth,
|
|
213
|
+
});
|
|
214
|
+
// Labeled ticks use human-friendly time intervals.
|
|
215
|
+
const secondTicks = [];
|
|
216
|
+
for (let index = 0; index < seconds; index += tickScale.labelEverySeconds) {
|
|
217
|
+
secondTicks.push({
|
|
117
218
|
frame: index * fps,
|
|
118
219
|
style: {
|
|
119
220
|
...secondTick,
|
|
120
221
|
left: frameInterval * index * fps + timeline_layout_1.TIMELINE_PADDING,
|
|
121
222
|
},
|
|
122
223
|
showTime: index > 0,
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
frame
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
const hasSecondTick = new Set(secondTicks.map((t) => t.frame));
|
|
227
|
+
const subdivisionTicks = [];
|
|
228
|
+
const { minorTickEvery, mediumTickEvery } = tickScale;
|
|
229
|
+
if ((minorTickEvery === null || minorTickEvery === void 0 ? void 0 : minorTickEvery.unit) === 'frames') {
|
|
230
|
+
for (let frame = 0; frame < durationInFrames; frame += minorTickEvery.interval) {
|
|
231
|
+
if (hasSecondTick.has(frame)) {
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
subdivisionTicks.push({
|
|
235
|
+
frame,
|
|
236
|
+
style: {
|
|
237
|
+
...tick,
|
|
238
|
+
left: frameInterval * frame + timeline_layout_1.TIMELINE_PADDING,
|
|
239
|
+
height: (Number.isInteger(fps) && frame % fps === 0) ||
|
|
240
|
+
((mediumTickEvery === null || mediumTickEvery === void 0 ? void 0 : mediumTickEvery.unit) === 'frames' &&
|
|
241
|
+
frame % mediumTickEvery.interval === 0)
|
|
137
242
|
? 5
|
|
138
243
|
: 2,
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
244
|
+
},
|
|
245
|
+
showTime: false,
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
if ((minorTickEvery === null || minorTickEvery === void 0 ? void 0 : minorTickEvery.unit) === 'seconds') {
|
|
250
|
+
for (let second = 0; second < seconds; second += minorTickEvery.interval) {
|
|
251
|
+
const frame = second * fps;
|
|
252
|
+
if (hasSecondTick.has(frame)) {
|
|
253
|
+
continue;
|
|
254
|
+
}
|
|
255
|
+
subdivisionTicks.push({
|
|
256
|
+
frame,
|
|
257
|
+
style: {
|
|
258
|
+
...tick,
|
|
259
|
+
left: frameInterval * frame + timeline_layout_1.TIMELINE_PADDING,
|
|
260
|
+
height: (mediumTickEvery === null || mediumTickEvery === void 0 ? void 0 : mediumTickEvery.unit) === 'seconds' &&
|
|
261
|
+
second % mediumTickEvery.interval === 0
|
|
262
|
+
? 5
|
|
263
|
+
: 2,
|
|
264
|
+
},
|
|
265
|
+
showTime: false,
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
return [...secondTicks, ...subdivisionTicks];
|
|
151
270
|
}, [durationInFrames, fps, windowWidth]);
|
|
152
271
|
return (jsx_runtime_1.jsx("div", { ref: ref, style: style, children: ticks.map((t) => {
|
|
153
272
|
return (jsx_runtime_1.jsx("div", { style: t.style, children: t.showTime ? (jsx_runtime_1.jsx("div", { style: tickLabel, children: (0, render_frame_1.renderFrame)(t.frame, fps) })) : null }, t.frame));
|
|
@@ -17,6 +17,7 @@ const containerStyle = {
|
|
|
17
17
|
display: 'flex',
|
|
18
18
|
gap: 4,
|
|
19
19
|
};
|
|
20
|
+
const translateDragSensitivity = 3;
|
|
20
21
|
const TimelineTranslateField = ({ field, propStatus, effectiveValue, onSave, onDragValueChange, onDragEnd, }) => {
|
|
21
22
|
const [dragX, setDragX] = (0, react_1.useState)(null);
|
|
22
23
|
const [dragY, setDragY] = (0, react_1.useState)(null);
|
|
@@ -100,7 +101,7 @@ const TimelineTranslateField = ({ field, propStatus, effectiveValue, onSave, onD
|
|
|
100
101
|
}
|
|
101
102
|
}, [propStatus, onSave, dragX, codeX, decimalPlaces]);
|
|
102
103
|
return (jsx_runtime_1.jsxs("span", { style: containerStyle, children: [
|
|
103
|
-
jsx_runtime_1.jsx(InputDragger_1.InputDragger, { type: "number", value: dragX !== null && dragX !== void 0 ? dragX : codeX, style: leftDraggerStyle, status: "ok", small: true, onValueChange: onXChange, onValueChangeEnd: onXChangeEnd, onTextChange: onXTextChange, min: -Infinity, max: Infinity, step: step, formatter: formatter, rightAlign: false, snapToStep: false, dragDecimalPlaces: decimalPlaces }), jsx_runtime_1.jsx("div", { style: { marginLeft: -6, marginRight: -6 } }), jsx_runtime_1.jsx(InputDragger_1.InputDragger, { type: "number", value: dragY !== null && dragY !== void 0 ? dragY : codeY, style: rightDraggerStyle, status: "ok", small: true, onValueChange: onYChange, onValueChangeEnd: onYChangeEnd, onTextChange: onYTextChange, min: -Infinity, max: Infinity, step: step, formatter: formatter, rightAlign: false, snapToStep: false, dragDecimalPlaces: decimalPlaces })
|
|
104
|
+
jsx_runtime_1.jsx(InputDragger_1.InputDragger, { type: "number", value: dragX !== null && dragX !== void 0 ? dragX : codeX, style: leftDraggerStyle, status: "ok", small: true, onValueChange: onXChange, onValueChangeEnd: onXChangeEnd, onTextChange: onXTextChange, min: -Infinity, max: Infinity, step: step, formatter: formatter, rightAlign: false, snapToStep: false, dragDecimalPlaces: decimalPlaces, dragSensitivity: translateDragSensitivity }), jsx_runtime_1.jsx("div", { style: { marginLeft: -6, marginRight: -6 } }), jsx_runtime_1.jsx(InputDragger_1.InputDragger, { type: "number", value: dragY !== null && dragY !== void 0 ? dragY : codeY, style: rightDraggerStyle, status: "ok", small: true, onValueChange: onYChange, onValueChangeEnd: onYChangeEnd, onTextChange: onYTextChange, min: -Infinity, max: Infinity, step: step, formatter: formatter, rightAlign: false, snapToStep: false, dragDecimalPlaces: decimalPlaces, dragSensitivity: translateDragSensitivity })
|
|
104
105
|
] }));
|
|
105
106
|
};
|
|
106
107
|
exports.TimelineTranslateField = TimelineTranslateField;
|
|
@@ -26,7 +26,7 @@ const filmstripContainerStyle = {
|
|
|
26
26
|
fontFamily: 'Arial, Helvetica',
|
|
27
27
|
};
|
|
28
28
|
const MAX_FROZEN_FRAME_CACHE_DEVIATION = timeline_utils_1.WEBCODECS_TIMESCALE * 0.05;
|
|
29
|
-
const TimelineVideoInfo = ({ src, visualizationWidth, naturalWidth, startMediaFrom, mediaFrameAtSequenceZero, sequenceFrameOffset, durationInFrames, playbackRate, volume, doesVolumeChange, premountWidth, postmountWidth, loopDisplay, frozenMediaFrame, }) => {
|
|
29
|
+
const TimelineVideoInfo = ({ src, visualizationWidth, naturalWidth, startMediaFrom, mediaFrameAtSequenceZero, sequenceFrameOffset, durationInFrames, playbackRate, volume, doesVolumeChange, premountWidth, postmountWidth, loopDisplay, frozenMediaFrame, extendLastFrame, }) => {
|
|
30
30
|
const { fps } = (0, remotion_1.useVideoConfig)();
|
|
31
31
|
const ref = (0, react_1.useRef)(null);
|
|
32
32
|
const [error, setError] = (0, react_1.useState)(null);
|
|
@@ -108,6 +108,7 @@ const TimelineVideoInfo = ({ src, visualizationWidth, naturalWidth, startMediaFr
|
|
|
108
108
|
};
|
|
109
109
|
}
|
|
110
110
|
(0, timeline_utils_1.extractFrames)({
|
|
111
|
+
repeatLastFrame: extendLastFrame,
|
|
111
112
|
timestampsInSeconds: ({ track, }) => {
|
|
112
113
|
aspectRatio.current = track.width / track.height;
|
|
113
114
|
timeline_utils_1.aspectRatioCache.set(src, aspectRatio.current);
|
|
@@ -216,6 +217,7 @@ const TimelineVideoInfo = ({ src, visualizationWidth, naturalWidth, startMediaFr
|
|
|
216
217
|
}
|
|
217
218
|
}
|
|
218
219
|
(0, timeline_utils_1.extractFrames)({
|
|
220
|
+
repeatLastFrame: extendLastFrame,
|
|
219
221
|
timestampsInSeconds: ({ track, }) => {
|
|
220
222
|
aspectRatio.current = track.width / track.height;
|
|
221
223
|
timeline_utils_1.aspectRatioCache.set(src, aspectRatio.current);
|
|
@@ -307,6 +309,7 @@ const TimelineVideoInfo = ({ src, visualizationWidth, naturalWidth, startMediaFr
|
|
|
307
309
|
}, [
|
|
308
310
|
durationInFrames,
|
|
309
311
|
error,
|
|
312
|
+
extendLastFrame,
|
|
310
313
|
fps,
|
|
311
314
|
frozenMediaFrame,
|
|
312
315
|
loopDisplay,
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type { OverrideIdToNodePaths, PropStatuses, TSequence } from 'remotion';
|
|
2
|
+
import type { SequenceNodePathInfo } from '../../helpers/get-timeline-sequence-sort-key';
|
|
2
3
|
import type { ConfirmationDialogFunction } from '../ConfirmationDialog-types';
|
|
3
4
|
import type { SetPropStatuses } from './save-sequence-prop';
|
|
4
5
|
import { type TimelineSelection } from './TimelineSelection';
|
|
6
|
+
export declare const deleteSequencesFromSource: (nodePathInfos: SequenceNodePathInfo[], confirm: ConfirmationDialogFunction) => Promise<boolean>;
|
|
5
7
|
export declare const deleteSelectedTimelineItem: ({ selection, sequences, overrideIdsToNodePaths, setPropStatuses, clientId, confirm, }: {
|
|
6
8
|
selection: TimelineSelection;
|
|
7
9
|
sequences: TSequence[];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.deleteSelectedTimelineItems = exports.getTimelineSelectionAfterDeletingItems = exports.deleteSelectedTimelineItem = void 0;
|
|
3
|
+
exports.deleteSelectedTimelineItems = exports.getTimelineSelectionAfterDeletingItems = exports.deleteSelectedTimelineItem = exports.deleteSequencesFromSource = void 0;
|
|
4
4
|
const remotion_1 = require("remotion");
|
|
5
5
|
const call_api_1 = require("../call-api");
|
|
6
6
|
const NotificationCenter_1 = require("../Notifications/NotificationCenter");
|
|
@@ -32,7 +32,7 @@ const confirmDeletingDuplicatedSequences = (nodePathInfos, confirm) => {
|
|
|
32
32
|
confirmLabel: 'Delete',
|
|
33
33
|
});
|
|
34
34
|
};
|
|
35
|
-
const
|
|
35
|
+
const deleteSequencesFromSource = async (nodePathInfos, confirm) => {
|
|
36
36
|
if (!(await confirmDeletingDuplicatedSequences(nodePathInfos, confirm))) {
|
|
37
37
|
return false;
|
|
38
38
|
}
|
|
@@ -61,6 +61,7 @@ const deleteSequences = async (nodePathInfos, confirm) => {
|
|
|
61
61
|
return true;
|
|
62
62
|
});
|
|
63
63
|
};
|
|
64
|
+
exports.deleteSequencesFromSource = deleteSequencesFromSource;
|
|
64
65
|
const deleteEffects = (effects) => {
|
|
65
66
|
if (effects.length === 0) {
|
|
66
67
|
return Promise.resolve(false);
|
|
@@ -115,7 +116,7 @@ const deleteSelectedTimelineItem = ({ selection, sequences, overrideIdsToNodePat
|
|
|
115
116
|
case 'guide':
|
|
116
117
|
return null;
|
|
117
118
|
case 'sequence':
|
|
118
|
-
return
|
|
119
|
+
return (0, exports.deleteSequencesFromSource)([selection.nodePathInfo], confirm);
|
|
119
120
|
case 'sequence-effect':
|
|
120
121
|
return deleteEffects([
|
|
121
122
|
{
|
|
@@ -286,7 +287,7 @@ const deleteSelectedTimelineItems = ({ selections, sequences, overrideIdsToNodeP
|
|
|
286
287
|
case 'guide':
|
|
287
288
|
return null;
|
|
288
289
|
case 'sequence':
|
|
289
|
-
return
|
|
290
|
+
return (0, exports.deleteSequencesFromSource)(selections
|
|
290
291
|
.filter(isSequenceRowSelection)
|
|
291
292
|
.map((selection) => selection.nodePathInfo), confirm);
|
|
292
293
|
case 'sequence-effect':
|
|
@@ -5,6 +5,8 @@ const no_react_1 = require("remotion/no-react");
|
|
|
5
5
|
const save_sequence_prop_1 = require("./save-sequence-prop");
|
|
6
6
|
const disableSequenceInteractivity = ({ clientId, fileName, nodePath, setPropStatuses, }) => {
|
|
7
7
|
return (0, save_sequence_prop_1.saveSequenceProps)({
|
|
8
|
+
addedKeyframes: null,
|
|
9
|
+
movedKeyframes: null,
|
|
8
10
|
changes: [
|
|
9
11
|
{
|
|
10
12
|
fileName,
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const getTimelineMediaVisualizationLayout: ({ visualizationWidth, premountWidth, postmountWidth, }: {
|
|
2
|
+
readonly visualizationWidth: number;
|
|
3
|
+
readonly premountWidth: number;
|
|
4
|
+
readonly postmountWidth: number;
|
|
5
|
+
}) => {
|
|
6
|
+
marginLeft: number;
|
|
7
|
+
width: number;
|
|
8
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getTimelineMediaVisualizationLayout = void 0;
|
|
4
|
+
const getTimelineMediaVisualizationLayout = ({ visualizationWidth, premountWidth, postmountWidth, }) => {
|
|
5
|
+
return {
|
|
6
|
+
marginLeft: premountWidth,
|
|
7
|
+
width: Math.max(0, visualizationWidth - premountWidth - postmountWidth),
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
exports.getTimelineMediaVisualizationLayout = getTimelineMediaVisualizationLayout;
|
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getTimelineVideoInfoWidths = void 0;
|
|
4
|
+
const get_timeline_media_visualization_layout_1 = require("./get-timeline-media-visualization-layout");
|
|
4
5
|
const getTimelineVideoInfoWidths = ({ visualizationWidth, naturalWidth, premountWidth, postmountWidth, }) => {
|
|
5
|
-
const mountWidth = premountWidth + postmountWidth;
|
|
6
6
|
return {
|
|
7
|
-
mediaVisualizationWidth:
|
|
8
|
-
|
|
7
|
+
mediaVisualizationWidth: (0, get_timeline_media_visualization_layout_1.getTimelineMediaVisualizationLayout)({
|
|
8
|
+
visualizationWidth,
|
|
9
|
+
premountWidth,
|
|
10
|
+
postmountWidth,
|
|
11
|
+
}).width,
|
|
12
|
+
mediaNaturalWidth: (0, get_timeline_media_visualization_layout_1.getTimelineMediaVisualizationLayout)({
|
|
13
|
+
visualizationWidth: naturalWidth,
|
|
14
|
+
premountWidth,
|
|
15
|
+
postmountWidth,
|
|
16
|
+
}).width,
|
|
9
17
|
};
|
|
10
18
|
};
|
|
11
19
|
exports.getTimelineVideoInfoWidths = getTimelineVideoInfoWidths;
|
|
@@ -182,6 +182,10 @@ const getKeyframeClipboardDataFromSelections = ({ selections, sequences, overrid
|
|
|
182
182
|
version: 1,
|
|
183
183
|
remotionClipboard: 'keyframe',
|
|
184
184
|
fieldType: firstResolved.fieldType,
|
|
185
|
+
field: {
|
|
186
|
+
type: firstResolved.identity.type,
|
|
187
|
+
fieldKey: firstResolved.identity.fieldKey,
|
|
188
|
+
},
|
|
185
189
|
keyframes: keyframes.map((keyframe) => {
|
|
186
190
|
return {
|
|
187
191
|
frameOffset: keyframe.frame - firstFrame,
|
|
@@ -214,15 +218,27 @@ const isKeyframeValueCompatible = ({ value, fieldType, }) => {
|
|
|
214
218
|
return typeof value === 'string';
|
|
215
219
|
};
|
|
216
220
|
const getPasteKeyframeTarget = ({ selectedItems, payload, timelinePosition, sequences, overrideIdsToNodePaths, propStatuses, }) => {
|
|
217
|
-
var _a, _b;
|
|
221
|
+
var _a, _b, _c;
|
|
218
222
|
if (selectedItems.length === 0) {
|
|
219
223
|
return { type: 'none' };
|
|
220
224
|
}
|
|
221
|
-
const
|
|
225
|
+
const resolvedSelectedItems = selectedItems.length === 1 &&
|
|
226
|
+
((_a = selectedItems[0]) === null || _a === void 0 ? void 0 : _a.type) === 'sequence' &&
|
|
227
|
+
payload.field !== null &&
|
|
228
|
+
payload.field.type === 'sequence'
|
|
229
|
+
? [
|
|
230
|
+
{
|
|
231
|
+
type: 'sequence-prop',
|
|
232
|
+
nodePathInfo: selectedItems[0].nodePathInfo,
|
|
233
|
+
key: payload.field.fieldKey,
|
|
234
|
+
},
|
|
235
|
+
]
|
|
236
|
+
: selectedItems;
|
|
237
|
+
const selection = resolvedSelectedItems[0];
|
|
222
238
|
if (!selection || getKeyframeFieldIdentity(selection) === null) {
|
|
223
239
|
return { type: 'none' };
|
|
224
240
|
}
|
|
225
|
-
const resolvedFields =
|
|
241
|
+
const resolvedFields = resolvedSelectedItems.map((item) => resolveKeyframeField({
|
|
226
242
|
selection: item,
|
|
227
243
|
sequences,
|
|
228
244
|
overrideIdsToNodePaths,
|
|
@@ -239,8 +255,8 @@ const getPasteKeyframeTarget = ({ selectedItems, payload, timelinePosition, sequ
|
|
|
239
255
|
sourceFrame: timelinePosition - resolved.keyframeDisplayOffset + keyframe.frameOffset,
|
|
240
256
|
value: keyframe.value,
|
|
241
257
|
}));
|
|
242
|
-
const firstFrame = (
|
|
243
|
-
const lastFrame = (
|
|
258
|
+
const firstFrame = (_b = keyframes[0]) === null || _b === void 0 ? void 0 : _b.sourceFrame;
|
|
259
|
+
const lastFrame = (_c = keyframes.at(-1)) === null || _c === void 0 ? void 0 : _c.sourceFrame;
|
|
244
260
|
if (firstFrame === undefined || lastFrame === undefined) {
|
|
245
261
|
return { type: 'incompatible' };
|
|
246
262
|
}
|
|
@@ -155,6 +155,8 @@ const resetSelectedTimelineProps = ({ selections, sequences, overrideIdsToNodePa
|
|
|
155
155
|
const resetPromises = [];
|
|
156
156
|
if (sequencePropTargets.length > 0) {
|
|
157
157
|
resetPromises.push((0, save_sequence_prop_1.saveSequenceProps)({
|
|
158
|
+
addedKeyframes: null,
|
|
159
|
+
movedKeyframes: null,
|
|
158
160
|
changes: sequencePropTargets.map((target) => ({
|
|
159
161
|
fileName: target.fileName,
|
|
160
162
|
nodePath: target.nodePath,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type SaveSequencePropSourceEdit } from '@remotion/studio-shared';
|
|
2
2
|
import type { CanUpdateSequencePropsResponse, SequencePropsSubscriptionKey, InteractivitySchema } from 'remotion';
|
|
3
|
+
import type { AddSequenceKeyframeChange } from './call-add-keyframe';
|
|
3
4
|
import { type MoveEffectKeyframeChange, type MoveSequenceKeyframeChange } from './call-move-keyframe';
|
|
4
5
|
export type SetPropStatuses = (nodePath: SequencePropsSubscriptionKey, values: (prev: CanUpdateSequencePropsResponse) => CanUpdateSequencePropsResponse) => void;
|
|
5
6
|
export type SaveSequencePropChange = {
|
|
@@ -13,14 +14,15 @@ export type SaveSequencePropChange = {
|
|
|
13
14
|
};
|
|
14
15
|
type SaveSequencePropsOptions = {
|
|
15
16
|
changes: SaveSequencePropChange[];
|
|
16
|
-
|
|
17
|
+
addedKeyframes: AddSequenceKeyframeChange[] | null;
|
|
18
|
+
movedKeyframes: {
|
|
17
19
|
sequenceKeyframes: MoveSequenceKeyframeChange[];
|
|
18
20
|
effectKeyframes: MoveEffectKeyframeChange[];
|
|
19
|
-
};
|
|
21
|
+
} | null;
|
|
20
22
|
setPropStatuses: SetPropStatuses;
|
|
21
23
|
clientId: string;
|
|
22
24
|
undoLabel: string;
|
|
23
25
|
redoLabel: string;
|
|
24
26
|
};
|
|
25
|
-
export declare const saveSequenceProps: ({ changes, movedKeyframes, setPropStatuses, clientId, undoLabel, redoLabel, }: SaveSequencePropsOptions) => Promise<void>;
|
|
27
|
+
export declare const saveSequenceProps: ({ changes, addedKeyframes, movedKeyframes, setPropStatuses, clientId, undoLabel, redoLabel, }: SaveSequencePropsOptions) => Promise<void>;
|
|
26
28
|
export {};
|
|
@@ -11,16 +11,18 @@ const serializeSequencePropValue = (value) => {
|
|
|
11
11
|
}
|
|
12
12
|
return { type: 'json', serialized: JSON.stringify(value) };
|
|
13
13
|
};
|
|
14
|
-
const saveSequenceProps = ({ changes, movedKeyframes, setPropStatuses, clientId, undoLabel, redoLabel, }) => {
|
|
15
|
-
|
|
16
|
-
const sequenceKeyframes =
|
|
17
|
-
const effectKeyframes =
|
|
14
|
+
const saveSequenceProps = ({ changes, addedKeyframes, movedKeyframes, setPropStatuses, clientId, undoLabel, redoLabel, }) => {
|
|
15
|
+
const keyframesToAdd = addedKeyframes === null ? [] : addedKeyframes;
|
|
16
|
+
const sequenceKeyframes = movedKeyframes === null ? [] : movedKeyframes.sequenceKeyframes;
|
|
17
|
+
const effectKeyframes = movedKeyframes === null ? [] : movedKeyframes.effectKeyframes;
|
|
18
18
|
if (changes.length === 0 &&
|
|
19
|
+
keyframesToAdd.length === 0 &&
|
|
19
20
|
sequenceKeyframes.length === 0 &&
|
|
20
21
|
effectKeyframes.length === 0) {
|
|
21
22
|
return Promise.resolve();
|
|
22
23
|
}
|
|
23
24
|
if (changes.length === 1 &&
|
|
25
|
+
keyframesToAdd.length === 0 &&
|
|
24
26
|
sequenceKeyframes.length === 0 &&
|
|
25
27
|
effectKeyframes.length === 0) {
|
|
26
28
|
const change = changes[0];
|
|
@@ -51,6 +53,8 @@ const saveSequenceProps = ({ changes, movedKeyframes, setPropStatuses, clientId,
|
|
|
51
53
|
sourceEdit: (_a = change.sourceEdit) !== null && _a !== void 0 ? _a : null,
|
|
52
54
|
},
|
|
53
55
|
],
|
|
56
|
+
addedKeyframes: null,
|
|
57
|
+
movedKeyframes: null,
|
|
54
58
|
clientId,
|
|
55
59
|
undoLabel,
|
|
56
60
|
redoLabel,
|
|
@@ -64,6 +68,15 @@ const saveSequenceProps = ({ changes, movedKeyframes, setPropStatuses, clientId,
|
|
|
64
68
|
effectKeyframes,
|
|
65
69
|
setPropStatuses,
|
|
66
70
|
});
|
|
71
|
+
for (const keyframe of keyframesToAdd) {
|
|
72
|
+
setPropStatuses(keyframe.nodePath, (prev) => (0, studio_shared_1.optimisticAddSequenceKeyframe)({
|
|
73
|
+
previous: prev,
|
|
74
|
+
fieldKey: keyframe.fieldKey,
|
|
75
|
+
frame: keyframe.sourceFrame,
|
|
76
|
+
value: keyframe.value,
|
|
77
|
+
schema: keyframe.schema,
|
|
78
|
+
}));
|
|
79
|
+
}
|
|
67
80
|
for (const change of changes) {
|
|
68
81
|
setPropStatuses(change.nodePath, (prev) => (0, studio_shared_1.optimisticUpdateForPropStatuses)({
|
|
69
82
|
previous: prev,
|
|
@@ -86,25 +99,37 @@ const saveSequenceProps = ({ changes, movedKeyframes, setPropStatuses, clientId,
|
|
|
86
99
|
sourceEdit: (_a = change.sourceEdit) !== null && _a !== void 0 ? _a : null,
|
|
87
100
|
};
|
|
88
101
|
}),
|
|
89
|
-
|
|
90
|
-
|
|
102
|
+
addedKeyframes: addedKeyframes === null
|
|
103
|
+
? null
|
|
104
|
+
: addedKeyframes.map((keyframe) => ({
|
|
91
105
|
fileName: keyframe.fileName,
|
|
92
106
|
nodePath: keyframe.nodePath,
|
|
93
107
|
key: keyframe.fieldKey,
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
schema: keyframe.schema,
|
|
97
|
-
})),
|
|
98
|
-
effectKeyframes: effectKeyframes.map((keyframe) => ({
|
|
99
|
-
fileName: keyframe.fileName,
|
|
100
|
-
sequenceNodePath: keyframe.nodePath,
|
|
101
|
-
effectIndex: keyframe.effectIndex,
|
|
102
|
-
key: keyframe.fieldKey,
|
|
103
|
-
fromFrame: keyframe.fromFrame,
|
|
104
|
-
toFrame: keyframe.toFrame,
|
|
108
|
+
frame: keyframe.sourceFrame,
|
|
109
|
+
value: JSON.stringify(keyframe.value),
|
|
105
110
|
schema: keyframe.schema,
|
|
106
111
|
})),
|
|
107
|
-
|
|
112
|
+
movedKeyframes: movedKeyframes === null
|
|
113
|
+
? null
|
|
114
|
+
: {
|
|
115
|
+
sequenceKeyframes: sequenceKeyframes.map((keyframe) => ({
|
|
116
|
+
fileName: keyframe.fileName,
|
|
117
|
+
nodePath: keyframe.nodePath,
|
|
118
|
+
key: keyframe.fieldKey,
|
|
119
|
+
fromFrame: keyframe.fromFrame,
|
|
120
|
+
toFrame: keyframe.toFrame,
|
|
121
|
+
schema: keyframe.schema,
|
|
122
|
+
})),
|
|
123
|
+
effectKeyframes: effectKeyframes.map((keyframe) => ({
|
|
124
|
+
fileName: keyframe.fileName,
|
|
125
|
+
sequenceNodePath: keyframe.nodePath,
|
|
126
|
+
effectIndex: keyframe.effectIndex,
|
|
127
|
+
key: keyframe.fieldKey,
|
|
128
|
+
fromFrame: keyframe.fromFrame,
|
|
129
|
+
toFrame: keyframe.toFrame,
|
|
130
|
+
schema: keyframe.schema,
|
|
131
|
+
})),
|
|
132
|
+
},
|
|
108
133
|
clientId,
|
|
109
134
|
undoLabel,
|
|
110
135
|
redoLabel,
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export declare const PREVENT_CLEAR_SELECTION_ON_POINTER_DOWN_ATTR = "data-remotion-prevent-selection-clear";
|
|
2
2
|
export declare const shouldClearSelectionOnPointerDown: (event: {
|
|
3
3
|
readonly button: number;
|
|
4
|
+
readonly ctrlKey: boolean | null;
|
|
5
|
+
readonly metaKey: boolean | null;
|
|
4
6
|
readonly target?: EventTarget | null | undefined;
|
|
5
7
|
}) => boolean;
|
|
@@ -13,7 +13,7 @@ const isSelectionClearBlocked = (target) => {
|
|
|
13
13
|
return (target.closest(`[${exports.PREVENT_CLEAR_SELECTION_ON_POINTER_DOWN_ATTR}]`) !== null);
|
|
14
14
|
};
|
|
15
15
|
const shouldClearSelectionOnPointerDown = (event) => {
|
|
16
|
-
if (event.button !== 0) {
|
|
16
|
+
if (event.button !== 0 || event.metaKey === true || event.ctrlKey === true) {
|
|
17
17
|
return false;
|
|
18
18
|
}
|
|
19
19
|
return !isSelectionClearBlocked(event.target);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const TimelineAssetDropFrameContext: import("react").Context<number | null>;
|
|
@@ -35,6 +35,13 @@ export declare const getFrameFromX: ({ clientX, durationInFrames, width, extrapo
|
|
|
35
35
|
width: number;
|
|
36
36
|
extrapolate: "clamp" | "extend";
|
|
37
37
|
}) => number;
|
|
38
|
+
export declare const getFrameFromTimelineDrop: ({ clientX, durationInFrames, scrollLeft, timelineLeft, timelineWidth, }: {
|
|
39
|
+
clientX: number;
|
|
40
|
+
durationInFrames: number;
|
|
41
|
+
scrollLeft: number;
|
|
42
|
+
timelineLeft: number;
|
|
43
|
+
timelineWidth: number;
|
|
44
|
+
}) => number;
|
|
38
45
|
/**
|
|
39
46
|
* Horizontal position inside the scrollable timeline content (0 … scrollWidth)
|
|
40
47
|
* for a viewport `clientX`, so pinch-anchoring matches the pointer (not a
|