@remotion/studio 4.0.444 → 4.0.446
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/AssetSelectorItem.js +11 -1
- package/dist/components/Canvas.js +197 -42
- package/dist/components/CanvasOrLoading.js +4 -4
- package/dist/components/CompositionSelectorItem.js +15 -1
- package/dist/components/FilePreview.js +3 -0
- package/dist/components/InitialCompositionLoader.js +10 -4
- package/dist/components/Preview.d.ts +1 -0
- package/dist/components/Preview.js +14 -1
- package/dist/components/Timeline/Timeline.js +8 -5
- package/dist/components/Timeline/TimelineListItem.js +53 -2
- package/dist/components/Timeline/TimelinePinchZoom.d.ts +2 -0
- package/dist/components/Timeline/TimelinePinchZoom.js +240 -0
- package/dist/components/Timeline/TimelineSlider.js +22 -8
- package/dist/components/Timeline/TimelineZoomControls.js +6 -3
- package/dist/components/Timeline/timeline-scroll-logic.d.ts +13 -1
- package/dist/components/Timeline/timeline-scroll-logic.js +20 -6
- package/dist/components/Timeline/use-sequence-props-subscription.d.ts +4 -1
- package/dist/components/Timeline/use-sequence-props-subscription.js +10 -1
- package/dist/error-overlay/remotion-overlay/ErrorDisplay.js +1 -1
- package/dist/error-overlay/remotion-overlay/Retry.d.ts +1 -0
- package/dist/error-overlay/remotion-overlay/Retry.js +2 -2
- package/dist/esm/{chunk-1zvzzrkf.js → chunk-2dkkw8x5.js} +6255 -5577
- package/dist/esm/internals.mjs +6255 -5577
- package/dist/esm/previewEntry.mjs +2250 -1574
- package/dist/esm/renderEntry.mjs +1 -1
- package/dist/helpers/get-asset-metadata.d.ts +3 -0
- package/dist/helpers/get-asset-metadata.js +51 -43
- package/dist/helpers/get-effective-translation.d.ts +13 -1
- package/dist/helpers/get-effective-translation.js +45 -1
- package/dist/helpers/sidebar-scroll-into-view.d.ts +13 -0
- package/dist/helpers/sidebar-scroll-into-view.js +83 -0
- package/dist/helpers/use-studio-canvas-dimensions.js +3 -1
- package/dist/state/timeline-zoom.d.ts +5 -1
- package/dist/state/timeline-zoom.js +21 -16
- package/package.json +9 -9
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TimelinePinchZoom = void 0;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const remotion_1 = require("remotion");
|
|
6
|
+
const is_current_selected_still_1 = require("../../helpers/is-current-selected-still");
|
|
7
|
+
const editor_zoom_gestures_1 = require("../../state/editor-zoom-gestures");
|
|
8
|
+
const timeline_zoom_1 = require("../../state/timeline-zoom");
|
|
9
|
+
const timeline_refs_1 = require("./timeline-refs");
|
|
10
|
+
const timeline_scroll_logic_1 = require("./timeline-scroll-logic");
|
|
11
|
+
/**
|
|
12
|
+
* Maps wheel deltaY to zoom delta. Must be large enough that typical ctrl+wheel
|
|
13
|
+
* pinch steps change `TimelineZoomCtx` zoom by at least one 0.1 step after
|
|
14
|
+
* `Math.round(z * 10) / 10` in `timeline-zoom.tsx` (0.005 was too small).
|
|
15
|
+
*/
|
|
16
|
+
const ZOOM_WHEEL_DELTA = 0.06;
|
|
17
|
+
const TimelinePinchZoom = () => {
|
|
18
|
+
const isVideoComposition = (0, is_current_selected_still_1.useIsVideoComposition)();
|
|
19
|
+
const videoConfig = remotion_1.Internals.useUnsafeVideoConfig();
|
|
20
|
+
const { canvasContent } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
|
|
21
|
+
const { zoom, setZoom } = (0, react_1.useContext)(timeline_zoom_1.TimelineZoomCtx);
|
|
22
|
+
const { editorZoomGestures } = (0, react_1.useContext)(editor_zoom_gestures_1.EditorZoomGesturesContext);
|
|
23
|
+
const zoomRef = (0, react_1.useRef)(zoom);
|
|
24
|
+
zoomRef.current = zoom;
|
|
25
|
+
const pinchBaseZoomRef = (0, react_1.useRef)(null);
|
|
26
|
+
const suppressWheelFromWebKitPinchRef = (0, react_1.useRef)(false);
|
|
27
|
+
const touchPinchRef = (0, react_1.useRef)(null);
|
|
28
|
+
const onWheel = (0, react_1.useCallback)((e) => {
|
|
29
|
+
if (!editorZoomGestures || !isVideoComposition) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const { ctrlKey, metaKey, clientX, deltaY, deltaMode } = e;
|
|
33
|
+
const wantsToZoom = ctrlKey || metaKey;
|
|
34
|
+
if (!wantsToZoom) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
if (suppressWheelFromWebKitPinchRef.current && wantsToZoom) {
|
|
38
|
+
e.preventDefault();
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (!videoConfig || videoConfig.durationInFrames < 2) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (!canvasContent || canvasContent.type !== 'composition') {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const scrollEl = timeline_refs_1.scrollableRef.current;
|
|
48
|
+
if (!scrollEl) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
e.preventDefault();
|
|
52
|
+
const anchorContentX = (0, timeline_scroll_logic_1.viewportClientXToScrollContentX)({
|
|
53
|
+
clientX,
|
|
54
|
+
scrollEl,
|
|
55
|
+
});
|
|
56
|
+
let scaledDeltaY = deltaY;
|
|
57
|
+
if (deltaMode === WheelEvent.DOM_DELTA_LINE) {
|
|
58
|
+
scaledDeltaY *= 16;
|
|
59
|
+
}
|
|
60
|
+
else if (deltaMode === WheelEvent.DOM_DELTA_PAGE) {
|
|
61
|
+
scaledDeltaY *= scrollEl.clientHeight;
|
|
62
|
+
}
|
|
63
|
+
setZoom(canvasContent.compositionId, (z) => z - scaledDeltaY * ZOOM_WHEEL_DELTA, { anchorFrame: null, anchorContentX });
|
|
64
|
+
}, [
|
|
65
|
+
editorZoomGestures,
|
|
66
|
+
isVideoComposition,
|
|
67
|
+
videoConfig,
|
|
68
|
+
canvasContent,
|
|
69
|
+
setZoom,
|
|
70
|
+
]);
|
|
71
|
+
const supportsWebKitPinch = typeof window !== 'undefined' && 'GestureEvent' in window;
|
|
72
|
+
(0, react_1.useEffect)(() => {
|
|
73
|
+
const el = timeline_refs_1.timelineVerticalScroll.current;
|
|
74
|
+
if (!el) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
el.addEventListener('wheel', onWheel, { passive: false });
|
|
78
|
+
return () => {
|
|
79
|
+
el.removeEventListener('wheel', onWheel);
|
|
80
|
+
};
|
|
81
|
+
}, [onWheel]);
|
|
82
|
+
(0, react_1.useEffect)(() => {
|
|
83
|
+
const el = timeline_refs_1.timelineVerticalScroll.current;
|
|
84
|
+
if (!el || !editorZoomGestures || !supportsWebKitPinch) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const endWebKitPinch = () => {
|
|
88
|
+
pinchBaseZoomRef.current = null;
|
|
89
|
+
suppressWheelFromWebKitPinchRef.current = false;
|
|
90
|
+
};
|
|
91
|
+
const onGestureStart = (event) => {
|
|
92
|
+
var _a;
|
|
93
|
+
const e = event;
|
|
94
|
+
if (!isVideoComposition) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if (!videoConfig || videoConfig.durationInFrames < 2) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
if (!canvasContent || canvasContent.type !== 'composition') {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const scrollEl = timeline_refs_1.scrollableRef.current;
|
|
104
|
+
if (!scrollEl) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
e.preventDefault();
|
|
108
|
+
suppressWheelFromWebKitPinchRef.current = true;
|
|
109
|
+
pinchBaseZoomRef.current = (_a = zoomRef.current[canvasContent.compositionId]) !== null && _a !== void 0 ? _a : timeline_zoom_1.TIMELINE_MIN_ZOOM;
|
|
110
|
+
};
|
|
111
|
+
const onGestureChange = (event) => {
|
|
112
|
+
const e = event;
|
|
113
|
+
const base = pinchBaseZoomRef.current;
|
|
114
|
+
if (base === null ||
|
|
115
|
+
!isVideoComposition ||
|
|
116
|
+
!videoConfig ||
|
|
117
|
+
videoConfig.durationInFrames < 2) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (!canvasContent || canvasContent.type !== 'composition') {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
const scrollEl = timeline_refs_1.scrollableRef.current;
|
|
124
|
+
if (!scrollEl) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
e.preventDefault();
|
|
128
|
+
const anchorContentX = (0, timeline_scroll_logic_1.viewportClientXToScrollContentX)({
|
|
129
|
+
clientX: e.clientX,
|
|
130
|
+
scrollEl,
|
|
131
|
+
});
|
|
132
|
+
setZoom(canvasContent.compositionId, () => base * e.scale, {
|
|
133
|
+
anchorFrame: null,
|
|
134
|
+
anchorContentX,
|
|
135
|
+
});
|
|
136
|
+
};
|
|
137
|
+
const onGestureEnd = () => {
|
|
138
|
+
endWebKitPinch();
|
|
139
|
+
};
|
|
140
|
+
el.addEventListener('gesturestart', onGestureStart, { passive: false });
|
|
141
|
+
el.addEventListener('gesturechange', onGestureChange, { passive: false });
|
|
142
|
+
el.addEventListener('gestureend', onGestureEnd);
|
|
143
|
+
el.addEventListener('gesturecancel', onGestureEnd);
|
|
144
|
+
return () => {
|
|
145
|
+
el.removeEventListener('gesturestart', onGestureStart);
|
|
146
|
+
el.removeEventListener('gesturechange', onGestureChange);
|
|
147
|
+
el.removeEventListener('gestureend', onGestureEnd);
|
|
148
|
+
el.removeEventListener('gesturecancel', onGestureEnd);
|
|
149
|
+
};
|
|
150
|
+
}, [
|
|
151
|
+
editorZoomGestures,
|
|
152
|
+
supportsWebKitPinch,
|
|
153
|
+
isVideoComposition,
|
|
154
|
+
videoConfig,
|
|
155
|
+
canvasContent,
|
|
156
|
+
setZoom,
|
|
157
|
+
]);
|
|
158
|
+
(0, react_1.useEffect)(() => {
|
|
159
|
+
const el = timeline_refs_1.timelineVerticalScroll.current;
|
|
160
|
+
if (!el || !editorZoomGestures) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
const onTouchStart = (event) => {
|
|
164
|
+
var _a;
|
|
165
|
+
if (event.touches.length !== 2) {
|
|
166
|
+
touchPinchRef.current = null;
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
if (!isVideoComposition ||
|
|
170
|
+
!videoConfig ||
|
|
171
|
+
videoConfig.durationInFrames < 2) {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
if (!canvasContent || canvasContent.type !== 'composition') {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
const [t0, t1] = [event.touches[0], event.touches[1]];
|
|
178
|
+
const initialDistance = Math.hypot(t1.clientX - t0.clientX, t1.clientY - t0.clientY);
|
|
179
|
+
if (initialDistance < 1e-6) {
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
touchPinchRef.current = {
|
|
183
|
+
initialDistance,
|
|
184
|
+
initialZoom: (_a = zoomRef.current[canvasContent.compositionId]) !== null && _a !== void 0 ? _a : timeline_zoom_1.TIMELINE_MIN_ZOOM,
|
|
185
|
+
};
|
|
186
|
+
};
|
|
187
|
+
const onTouchMove = (event) => {
|
|
188
|
+
const pinch = touchPinchRef.current;
|
|
189
|
+
if (pinch === null ||
|
|
190
|
+
event.touches.length !== 2 ||
|
|
191
|
+
!videoConfig ||
|
|
192
|
+
videoConfig.durationInFrames < 2) {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
if (!canvasContent || canvasContent.type !== 'composition') {
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
const scrollEl = timeline_refs_1.scrollableRef.current;
|
|
199
|
+
if (!scrollEl) {
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
event.preventDefault();
|
|
203
|
+
const [t0, t1] = [event.touches[0], event.touches[1]];
|
|
204
|
+
const dist = Math.hypot(t1.clientX - t0.clientX, t1.clientY - t0.clientY);
|
|
205
|
+
const ratio = dist / pinch.initialDistance;
|
|
206
|
+
const clientX = (t0.clientX + t1.clientX) / 2;
|
|
207
|
+
const anchorContentX = (0, timeline_scroll_logic_1.viewportClientXToScrollContentX)({
|
|
208
|
+
clientX,
|
|
209
|
+
scrollEl,
|
|
210
|
+
});
|
|
211
|
+
setZoom(canvasContent.compositionId, () => pinch.initialZoom * ratio, {
|
|
212
|
+
anchorFrame: null,
|
|
213
|
+
anchorContentX,
|
|
214
|
+
});
|
|
215
|
+
};
|
|
216
|
+
const onTouchEnd = (event) => {
|
|
217
|
+
if (event.touches.length < 2) {
|
|
218
|
+
touchPinchRef.current = null;
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
el.addEventListener('touchstart', onTouchStart, { passive: true });
|
|
222
|
+
el.addEventListener('touchmove', onTouchMove, { passive: false });
|
|
223
|
+
el.addEventListener('touchend', onTouchEnd);
|
|
224
|
+
el.addEventListener('touchcancel', onTouchEnd);
|
|
225
|
+
return () => {
|
|
226
|
+
el.removeEventListener('touchstart', onTouchStart);
|
|
227
|
+
el.removeEventListener('touchmove', onTouchMove);
|
|
228
|
+
el.removeEventListener('touchend', onTouchEnd);
|
|
229
|
+
el.removeEventListener('touchcancel', onTouchEnd);
|
|
230
|
+
};
|
|
231
|
+
}, [
|
|
232
|
+
editorZoomGestures,
|
|
233
|
+
isVideoComposition,
|
|
234
|
+
videoConfig,
|
|
235
|
+
canvasContent,
|
|
236
|
+
setZoom,
|
|
237
|
+
]);
|
|
238
|
+
return null;
|
|
239
|
+
};
|
|
240
|
+
exports.TimelinePinchZoom = TimelinePinchZoom;
|
|
@@ -5,6 +5,7 @@ const jsx_runtime_1 = require("react/jsx-runtime");
|
|
|
5
5
|
const react_1 = require("react");
|
|
6
6
|
const remotion_1 = require("remotion");
|
|
7
7
|
const get_left_of_timeline_slider_1 = require("../../helpers/get-left-of-timeline-slider");
|
|
8
|
+
const timeline_zoom_1 = require("../../state/timeline-zoom");
|
|
8
9
|
const imperative_state_1 = require("./imperative-state");
|
|
9
10
|
const timeline_refs_1 = require("./timeline-refs");
|
|
10
11
|
const TimelineSliderHandle_1 = require("./TimelineSliderHandle");
|
|
@@ -32,20 +33,33 @@ const TimelineSlider = () => {
|
|
|
32
33
|
};
|
|
33
34
|
exports.TimelineSlider = TimelineSlider;
|
|
34
35
|
const Inner = () => {
|
|
36
|
+
var _a;
|
|
35
37
|
const videoConfig = (0, remotion_1.useVideoConfig)();
|
|
36
38
|
const timelinePosition = remotion_1.Internals.Timeline.useTimelinePosition();
|
|
37
39
|
const ref = (0, react_1.useRef)(null);
|
|
38
40
|
const timelineWidth = (0, react_1.useContext)(TimelineWidthProvider_1.TimelineWidthContext);
|
|
41
|
+
const { zoom: zoomMap } = (0, react_1.useContext)(timeline_zoom_1.TimelineZoomCtx);
|
|
42
|
+
const { canvasContent } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
|
|
39
43
|
if (timelineWidth === null) {
|
|
40
44
|
throw new Error('Unexpectedly did not have timeline width');
|
|
41
45
|
}
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
const zoomLevel = (canvasContent === null || canvasContent === void 0 ? void 0 : canvasContent.type) === 'composition'
|
|
47
|
+
? ((_a = zoomMap[canvasContent.compositionId]) !== null && _a !== void 0 ? _a : timeline_zoom_1.TIMELINE_MIN_ZOOM)
|
|
48
|
+
: timeline_zoom_1.TIMELINE_MIN_ZOOM;
|
|
49
|
+
(0, react_1.useLayoutEffect)(() => {
|
|
50
|
+
var _a;
|
|
51
|
+
const el = ref.current;
|
|
52
|
+
const measuredWidth = (_a = timeline_refs_1.sliderAreaRef.current) === null || _a === void 0 ? void 0 : _a.clientWidth;
|
|
53
|
+
if (!el || measuredWidth === undefined || measuredWidth === 0) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
el.style.transform = `translateX(${(0, get_left_of_timeline_slider_1.getXPositionOfItemInTimelineImperatively)(timelinePosition, videoConfig.durationInFrames, measuredWidth)}px)`;
|
|
57
|
+
}, [
|
|
58
|
+
timelinePosition,
|
|
59
|
+
videoConfig.durationInFrames,
|
|
60
|
+
timelineWidth,
|
|
61
|
+
zoomLevel,
|
|
62
|
+
]);
|
|
49
63
|
(0, react_1.useImperativeHandle)(exports.redrawTimelineSliderFast, () => {
|
|
50
64
|
return {
|
|
51
65
|
draw: (frame, width) => {
|
|
@@ -76,7 +90,7 @@ const Inner = () => {
|
|
|
76
90
|
current.removeEventListener('scroll', onScroll);
|
|
77
91
|
};
|
|
78
92
|
}, []);
|
|
79
|
-
return (jsx_runtime_1.jsxs("div", { ref: ref, style:
|
|
93
|
+
return (jsx_runtime_1.jsxs("div", { ref: ref, style: container, children: [
|
|
80
94
|
jsx_runtime_1.jsx("div", { style: line }), jsx_runtime_1.jsx(TimelineSliderHandle_1.TimelineSliderHandle, {})
|
|
81
95
|
] }));
|
|
82
96
|
};
|
|
@@ -33,19 +33,22 @@ const TimelineZoomControls = () => {
|
|
|
33
33
|
if (canvasContent === null || canvasContent.type !== 'composition') {
|
|
34
34
|
return;
|
|
35
35
|
}
|
|
36
|
-
setZoom(canvasContent.compositionId, (z) => Math.max(timeline_zoom_1.TIMELINE_MIN_ZOOM, z - 0.2));
|
|
36
|
+
setZoom(canvasContent.compositionId, (z) => Math.max(timeline_zoom_1.TIMELINE_MIN_ZOOM, z - 0.2), { anchorFrame: null, anchorContentX: null });
|
|
37
37
|
}, [canvasContent, setZoom]);
|
|
38
38
|
const onPlusClicked = (0, react_1.useCallback)(() => {
|
|
39
39
|
if (canvasContent === null || canvasContent.type !== 'composition') {
|
|
40
40
|
return;
|
|
41
41
|
}
|
|
42
|
-
setZoom(canvasContent.compositionId, (z) => Math.min(timeline_zoom_1.TIMELINE_MAX_ZOOM, z + 0.2));
|
|
42
|
+
setZoom(canvasContent.compositionId, (z) => Math.min(timeline_zoom_1.TIMELINE_MAX_ZOOM, z + 0.2), { anchorFrame: null, anchorContentX: null });
|
|
43
43
|
}, [canvasContent, setZoom]);
|
|
44
44
|
const onChange = (0, react_1.useCallback)((e) => {
|
|
45
45
|
if (canvasContent === null || canvasContent.type !== 'composition') {
|
|
46
46
|
return;
|
|
47
47
|
}
|
|
48
|
-
setZoom(canvasContent.compositionId, () => Number(e.target.value)
|
|
48
|
+
setZoom(canvasContent.compositionId, () => Number(e.target.value), {
|
|
49
|
+
anchorFrame: null,
|
|
50
|
+
anchorContentX: null,
|
|
51
|
+
});
|
|
49
52
|
}, [canvasContent, setZoom]);
|
|
50
53
|
const isStill = (0, is_current_selected_still_1.useIsStill)();
|
|
51
54
|
if (isStill ||
|
|
@@ -35,9 +35,21 @@ export declare const getFrameFromX: ({ clientX, durationInFrames, width, extrapo
|
|
|
35
35
|
width: number;
|
|
36
36
|
extrapolate: "clamp" | "extend";
|
|
37
37
|
}) => number;
|
|
38
|
-
|
|
38
|
+
/**
|
|
39
|
+
* Horizontal position inside the scrollable timeline content (0 … scrollWidth)
|
|
40
|
+
* for a viewport `clientX`, so pinch-anchoring matches the pointer (not a
|
|
41
|
+
* rounded frame index).
|
|
42
|
+
*/
|
|
43
|
+
export declare const viewportClientXToScrollContentX: ({ clientX, scrollEl, }: {
|
|
44
|
+
clientX: number;
|
|
45
|
+
scrollEl: HTMLDivElement;
|
|
46
|
+
}) => number;
|
|
47
|
+
export declare const zoomAndPreserveCursor: ({ oldZoom, newZoom, currentFrame, currentDurationInFrames, anchorFrame, anchorContentX, }: {
|
|
39
48
|
oldZoom: number;
|
|
40
49
|
newZoom: number;
|
|
41
50
|
currentFrame: number;
|
|
42
51
|
currentDurationInFrames: number;
|
|
52
|
+
anchorFrame: number | null;
|
|
53
|
+
/** Prefer this over `anchorFrame` when not null (subpixel-accurate anchor). */
|
|
54
|
+
anchorContentX: number | null;
|
|
43
55
|
}) => void;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.zoomAndPreserveCursor = exports.getFrameFromX = exports.getFrameWhileScrollingRight = exports.getFrameIncrementFromWidth = exports.getScrollPositionForCursorOnRightEdge = exports.getScrollPositionForCursorOnLeftEdge = exports.scrollToTimelineXOffset = exports.ensureFrameIsInViewport = exports.isCursorInViewport = exports.getFrameWhileScrollingLeft = exports.canScrollTimelineIntoDirection = void 0;
|
|
3
|
+
exports.zoomAndPreserveCursor = exports.viewportClientXToScrollContentX = exports.getFrameFromX = exports.getFrameWhileScrollingRight = exports.getFrameIncrementFromWidth = exports.getScrollPositionForCursorOnRightEdge = exports.getScrollPositionForCursorOnLeftEdge = exports.scrollToTimelineXOffset = exports.ensureFrameIsInViewport = exports.isCursorInViewport = exports.getFrameWhileScrollingLeft = exports.canScrollTimelineIntoDirection = void 0;
|
|
4
4
|
const remotion_1 = require("remotion");
|
|
5
5
|
const timeline_layout_1 = require("../../helpers/timeline-layout");
|
|
6
6
|
const timeline_refs_1 = require("./timeline-refs");
|
|
@@ -200,9 +200,18 @@ const getFrameFromX = ({ clientX, durationInFrames, width, extrapolate, }) => {
|
|
|
200
200
|
return frame;
|
|
201
201
|
};
|
|
202
202
|
exports.getFrameFromX = getFrameFromX;
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
203
|
+
/**
|
|
204
|
+
* Horizontal position inside the scrollable timeline content (0 … scrollWidth)
|
|
205
|
+
* for a viewport `clientX`, so pinch-anchoring matches the pointer (not a
|
|
206
|
+
* rounded frame index).
|
|
207
|
+
*/
|
|
208
|
+
const viewportClientXToScrollContentX = ({ clientX, scrollEl, }) => {
|
|
209
|
+
const rect = scrollEl.getBoundingClientRect();
|
|
210
|
+
const clampedClientX = Math.min(Math.max(clientX, rect.left), rect.right);
|
|
211
|
+
return clampedClientX + scrollEl.scrollLeft - rect.left;
|
|
212
|
+
};
|
|
213
|
+
exports.viewportClientXToScrollContentX = viewportClientXToScrollContentX;
|
|
214
|
+
const zoomAndPreserveCursor = ({ oldZoom, newZoom, currentFrame, currentDurationInFrames, anchorFrame, anchorContentX, }) => {
|
|
206
215
|
const ratio = newZoom / oldZoom;
|
|
207
216
|
if (ratio === 1) {
|
|
208
217
|
return;
|
|
@@ -212,9 +221,14 @@ const zoomAndPreserveCursor = ({ oldZoom, newZoom, currentFrame, currentDuration
|
|
|
212
221
|
return;
|
|
213
222
|
}
|
|
214
223
|
const frameIncrement = getFrameIncrement(currentDurationInFrames);
|
|
215
|
-
const
|
|
224
|
+
const frameForScroll = anchorFrame !== null && anchorFrame !== void 0 ? anchorFrame : currentFrame;
|
|
225
|
+
const prevCursorPosition = anchorContentX !== null
|
|
226
|
+
? Math.min(Math.max(anchorContentX, 0), current.scrollWidth)
|
|
227
|
+
: frameIncrement * frameForScroll + timeline_layout_1.TIMELINE_PADDING;
|
|
216
228
|
const newCursorPosition = ratio * (prevCursorPosition - timeline_layout_1.TIMELINE_PADDING) + timeline_layout_1.TIMELINE_PADDING;
|
|
217
229
|
current.scrollLeft += newCursorPosition - prevCursorPosition;
|
|
218
|
-
|
|
230
|
+
// Playhead position is synced in `TimelineSlider` `useLayoutEffect` using
|
|
231
|
+
// measured `sliderAreaRef.clientWidth` so it matches layout after zoom
|
|
232
|
+
// (avoids fighting React `style` with stale `timelineWidth` during pinch).
|
|
219
233
|
};
|
|
220
234
|
exports.zoomAndPreserveCursor = zoomAndPreserveCursor;
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import type { SequenceNodePath } from '@remotion/studio-shared';
|
|
2
2
|
import type { TSequence } from 'remotion';
|
|
3
3
|
import type { OriginalPosition } from '../../error-overlay/react-overlay/utils/get-source-map';
|
|
4
|
-
export declare const useSequencePropsSubscription: (sequence: TSequence, originalLocation: OriginalPosition | null, visualModeEnabled: boolean) =>
|
|
4
|
+
export declare const useSequencePropsSubscription: (sequence: TSequence, originalLocation: OriginalPosition | null, visualModeEnabled: boolean) => {
|
|
5
|
+
nodePath: SequenceNodePath | null;
|
|
6
|
+
jsxInMapCallback: boolean;
|
|
7
|
+
};
|
|
@@ -45,6 +45,7 @@ const useSequencePropsSubscription = (sequence, originalLocation, visualModeEnab
|
|
|
45
45
|
currentLocationColumn.current = locationColumn;
|
|
46
46
|
const nodePathRef = (0, react_1.useRef)(null);
|
|
47
47
|
const [nodePath, setNodePath] = (0, react_1.useState)(null);
|
|
48
|
+
const [jsxInMapCallback, setJsxInMapCallback] = (0, react_1.useState)(false);
|
|
48
49
|
const isMountedRef = (0, react_1.useRef)(true);
|
|
49
50
|
const setNodePathBoth = (0, react_1.useCallback)((next) => {
|
|
50
51
|
nodePathRef.current = next;
|
|
@@ -60,6 +61,7 @@ const useSequencePropsSubscription = (sequence, originalLocation, visualModeEnab
|
|
|
60
61
|
if (!visualModeEnabled) {
|
|
61
62
|
setPropStatusesForSequence(null);
|
|
62
63
|
setNodePathBoth(null);
|
|
64
|
+
setJsxInMapCallback(false);
|
|
63
65
|
return;
|
|
64
66
|
}
|
|
65
67
|
if (!clientId ||
|
|
@@ -69,6 +71,7 @@ const useSequencePropsSubscription = (sequence, originalLocation, visualModeEnab
|
|
|
69
71
|
!schemaKeysString) {
|
|
70
72
|
setPropStatusesForSequence(null);
|
|
71
73
|
setNodePathBoth(null);
|
|
74
|
+
setJsxInMapCallback(false);
|
|
72
75
|
return;
|
|
73
76
|
}
|
|
74
77
|
const keys = schemaKeysString.split(',');
|
|
@@ -88,14 +91,17 @@ const useSequencePropsSubscription = (sequence, originalLocation, visualModeEnab
|
|
|
88
91
|
if (result.canUpdate) {
|
|
89
92
|
setNodePathBoth(result.nodePath);
|
|
90
93
|
setPropStatusesForSequence(result.props);
|
|
94
|
+
setJsxInMapCallback(result.jsxInMapCallback);
|
|
91
95
|
}
|
|
92
96
|
else {
|
|
93
97
|
setNodePathBoth(null);
|
|
94
98
|
setPropStatusesForSequence(null);
|
|
99
|
+
setJsxInMapCallback(false);
|
|
95
100
|
}
|
|
96
101
|
})
|
|
97
102
|
.catch((err) => {
|
|
98
103
|
setNodePathBoth(null);
|
|
104
|
+
setJsxInMapCallback(false);
|
|
99
105
|
remotion_1.Internals.Log.error(err);
|
|
100
106
|
setPropStatusesForSequence(null);
|
|
101
107
|
});
|
|
@@ -107,6 +113,7 @@ const useSequencePropsSubscription = (sequence, originalLocation, visualModeEnab
|
|
|
107
113
|
setPropStatusesForSequence(null);
|
|
108
114
|
}
|
|
109
115
|
setNodePathBoth(null);
|
|
116
|
+
setJsxInMapCallback(false);
|
|
110
117
|
if (currentNodePath) {
|
|
111
118
|
(0, call_api_1.callApi)('/api/unsubscribe-from-sequence-props', {
|
|
112
119
|
fileName: locationSource,
|
|
@@ -145,10 +152,12 @@ const useSequencePropsSubscription = (sequence, originalLocation, visualModeEnab
|
|
|
145
152
|
}
|
|
146
153
|
if (event.result.canUpdate) {
|
|
147
154
|
setPropStatusesForSequence(event.result.props);
|
|
155
|
+
setJsxInMapCallback(event.result.jsxInMapCallback);
|
|
148
156
|
}
|
|
149
157
|
else {
|
|
150
158
|
setPropStatusesForSequence(null);
|
|
151
159
|
setNodePathBoth(null);
|
|
160
|
+
setJsxInMapCallback(false);
|
|
152
161
|
}
|
|
153
162
|
};
|
|
154
163
|
const unsub = subscribeToEvent('sequence-props-updated', listener);
|
|
@@ -164,6 +173,6 @@ const useSequencePropsSubscription = (sequence, originalLocation, visualModeEnab
|
|
|
164
173
|
setPropStatusesForSequence,
|
|
165
174
|
setNodePathBoth,
|
|
166
175
|
]);
|
|
167
|
-
return nodePath;
|
|
176
|
+
return { nodePath, jsxInMapCallback };
|
|
168
177
|
};
|
|
169
178
|
exports.useSequencePropsSubscription = useSequencePropsSubscription;
|
|
@@ -65,7 +65,7 @@ const ErrorDisplay = ({ display, keyboardShortcuts, onRetry, canHaveDismissButto
|
|
|
65
65
|
] })) : null, display.stackFrames.length > 0 && window.remotion_editorName ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
|
|
66
66
|
jsx_runtime_1.jsx(OpenInEditor_1.OpenInEditor, { canHaveKeyboardShortcuts: keyboardShortcuts, stack: display.stackFrames[0] }), jsx_runtime_1.jsx("div", { style: spacer })
|
|
67
67
|
] })) : null, jsx_runtime_1.jsx(CopyStackTrace_1.CopyStackTrace, { canHaveKeyboardShortcuts: keyboardShortcuts, errorText: errorTextForCopy }), jsx_runtime_1.jsx("div", { style: spacer }), jsx_runtime_1.jsx(SearchGitHubIssues_1.SearchGithubIssues, { canHaveKeyboardShortcuts: keyboardShortcuts, message: display.error.message }), jsx_runtime_1.jsx("div", { style: spacer }), jsx_runtime_1.jsx(AskOnDiscord_1.AskOnDiscord, { canHaveKeyboardShortcuts: keyboardShortcuts }), onRetry ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
|
|
68
|
-
jsx_runtime_1.jsx("div", { style: spacer }), jsx_runtime_1.jsx(Retry_1.RetryButton, { onClick: onRetry })
|
|
68
|
+
jsx_runtime_1.jsx("div", { style: spacer }), jsx_runtime_1.jsx(Retry_1.RetryButton, { onClick: onRetry, label: calculateMetadata ? 'Retry calculateMetadata()' : 'Retry' })
|
|
69
69
|
] })) : null, calculateMetadata ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
|
|
70
70
|
jsx_runtime_1.jsx("br", {}), jsx_runtime_1.jsx(layout_1.Spacing, { y: 0.5 }), jsx_runtime_1.jsx(CalculateMetadataErrorExplainer_1.CalculateMetadataErrorExplainer, {})
|
|
71
71
|
] })) : null, display.error instanceof remotion_1.MediaPlaybackError ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.RetryButton = void 0;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
const Button_1 = require("../../components/Button");
|
|
6
|
-
const RetryButton = ({ onClick }) => {
|
|
7
|
-
return jsx_runtime_1.jsx(Button_1.Button, { onClick: onClick, children:
|
|
6
|
+
const RetryButton = ({ onClick, label = 'Retry' }) => {
|
|
7
|
+
return jsx_runtime_1.jsx(Button_1.Button, { onClick: onClick, children: label });
|
|
8
8
|
};
|
|
9
9
|
exports.RetryButton = RetryButton;
|