@remotion/studio 4.0.519 → 4.0.521
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/api/shut-down-studio.d.ts +6 -0
- package/dist/api/shut-down-studio.js +23 -0
- package/dist/api/visual-control.js +2 -2
- package/dist/components/AudioWaveform.js +16 -7
- package/dist/components/Canvas.js +114 -48
- package/dist/components/CaptionInspector.d.ts +1 -0
- package/dist/components/CaptionInspector.js +43 -2
- package/dist/components/CaptionTextEditor.js +1 -1
- package/dist/components/CompositionSelector.js +41 -34
- package/dist/components/CompositionSelectorItem.d.ts +7 -0
- package/dist/components/CompositionSelectorItem.js +344 -73
- package/dist/components/CurrentCompositionSideEffects.js +5 -0
- package/dist/components/ElementInstallConfirmation.d.ts +2 -23
- package/dist/components/ElementInstallConfirmation.js +89 -65
- package/dist/components/ElementLibraryModal.js +3 -1
- package/dist/components/FpsCounter.js +1 -1
- package/dist/components/FramePersistor.js +1 -1
- package/dist/components/InlineCaptionInspector.js +37 -1
- package/dist/components/InspectorPanel/ElementLibraryButton.js +3 -18
- package/dist/components/InspectorPanel/SequenceSelectionInspector.js +4 -3
- package/dist/components/InspectorPanel/use-composition-actions.js +5 -8
- package/dist/components/InspectorSequenceSection.js +1 -4
- package/dist/components/Menu/MenuSubItem.js +1 -1
- package/dist/components/ModalContainer.d.ts +1 -0
- package/dist/components/ModalContainer.js +2 -2
- package/dist/components/ModalHeader.js +5 -1
- package/dist/components/Modals.js +1 -1
- package/dist/components/NewComposition/NewComposition.js +2 -2
- package/dist/components/PlayPause.js +2 -13
- package/dist/components/PreviewToolbar.js +1 -1
- package/dist/components/QuickSwitcher/QuickSwitcherContent.js +29 -15
- package/dist/components/QuickSwitcher/QuickSwitcherResult.d.ts +14 -1
- package/dist/components/QuickSwitcher/QuickSwitcherResult.js +64 -9
- package/dist/components/QuickSwitcher/asset-search.d.ts +0 -1
- package/dist/components/QuickSwitcher/asset-search.js +1 -16
- package/dist/components/QuickSwitcher/composition-search.d.ts +16 -0
- package/dist/components/QuickSwitcher/composition-search.js +136 -0
- package/dist/components/RenderButton.js +2 -2
- package/dist/components/RenderModal/RenderStatusModal.js +7 -1
- package/dist/components/RenderModal/ServerRenderModal.js +1 -1
- package/dist/components/RenderModal/WebRenderModal.js +1 -1
- package/dist/components/RenderQueue/ClientRenderQueueProcessor.js +1 -1
- package/dist/components/ResetZoomButton.js +17 -2
- package/dist/components/SelectedOutlineElement.js +10 -30
- package/dist/components/SettingsModal.js +8 -5
- package/dist/components/TimeValue.js +36 -7
- package/dist/components/Timeline/Timeline.d.ts +1 -1
- package/dist/components/Timeline/Timeline.js +33 -20
- package/dist/components/Timeline/TimelineAssetField.d.ts +0 -1
- package/dist/components/Timeline/TimelineAssetField.js +17 -9
- package/dist/components/Timeline/TimelineCollapseToggle.js +1 -1
- package/dist/components/Timeline/TimelineDeleteKeybindings.js +5 -90
- package/dist/components/Timeline/TimelineDragHandler.js +18 -8
- package/dist/components/Timeline/TimelineFontWeightField.d.ts +11 -0
- package/dist/components/Timeline/TimelineFontWeightField.js +65 -0
- package/dist/components/Timeline/TimelineInOutDragHandler.js +2 -3
- package/dist/components/Timeline/TimelineLayerChildren.d.ts +21 -0
- package/dist/components/Timeline/TimelineLayerChildren.js +129 -0
- package/dist/components/Timeline/TimelineNumberField.js +13 -5
- package/dist/components/Timeline/TimelinePinchZoom.js +14 -4
- package/dist/components/Timeline/TimelinePlayCursorSyncer.js +8 -4
- package/dist/components/Timeline/TimelinePrimitiveFieldValue.js +4 -0
- package/dist/components/Timeline/TimelineSequence.js +54 -73
- package/dist/components/Timeline/TimelineSequenceItem.js +16 -36
- package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +22 -10
- package/dist/components/Timeline/TimelineSlider.js +2 -2
- package/dist/components/Timeline/TimelineTickFormatProvider.d.ts +8 -0
- package/dist/components/Timeline/TimelineTickFormatProvider.js +16 -0
- package/dist/components/Timeline/TimelineTimeIndicators.js +7 -3
- package/dist/components/Timeline/TimelineVideoInfo.js +7 -3
- package/dist/components/Timeline/TimelineWidthProvider.js +15 -8
- package/dist/components/Timeline/TimelineZoomControls.js +25 -8
- package/dist/components/Timeline/delete-selected-timeline-item.js +2 -2
- package/dist/components/Timeline/timeline-field-display-utils.js +1 -0
- package/dist/components/Timeline/timeline-scroll-logic.d.ts +1 -0
- package/dist/components/Timeline/timeline-scroll-logic.js +21 -17
- package/dist/components/Timeline/use-delete-timeline-items.d.ts +1 -0
- package/dist/components/Timeline/use-delete-timeline-items.js +118 -0
- package/dist/components/Timeline/use-timeline-asset-drop.js +8 -14
- package/dist/components/UpdateStatusContext.d.ts +5 -0
- package/dist/components/UpdateStatusContext.js +53 -2
- package/dist/components/UpdatesSettings.js +25 -4
- package/dist/components/WebMcp.js +87 -8
- package/dist/components/ZoomPersistor.js +2 -2
- package/dist/components/composition-drag-data.d.ts +36 -0
- package/dist/components/composition-drag-data.js +232 -0
- package/dist/components/composition-selector-drag-data.d.ts +27 -0
- package/dist/components/composition-selector-drag-data.js +80 -0
- package/dist/components/drop-handler-data.d.ts +2 -1
- package/dist/components/drop-handler-data.js +6 -4
- package/dist/components/effect-drag-and-drop.d.ts +2 -5
- package/dist/components/handle-drop.js +6 -2
- package/dist/components/import-assets.d.ts +7 -14
- package/dist/components/import-assets.js +11 -1
- package/dist/components/parse-caption-file.d.ts +5 -0
- package/dist/components/parse-caption-file.js +63 -0
- package/dist/error-overlay/current-error.d.ts +13 -0
- package/dist/error-overlay/current-error.js +21 -0
- package/dist/error-overlay/remotion-overlay/ErrorLoader.js +5 -1
- package/dist/esm/chunk-emw4k5b0.js +99527 -0
- package/dist/esm/{chunk-1fkq5bfq.js → chunk-vkrvnx2h.js} +20116 -16283
- package/dist/esm/index.mjs +27 -9
- package/dist/esm/internals.mjs +17408 -13426
- package/dist/esm/previewEntry.mjs +17285 -13216
- package/dist/esm/renderEntry.mjs +1 -1
- package/dist/helpers/create-folder-tree.js +2 -5
- package/dist/helpers/document-title.d.ts +2 -0
- package/dist/helpers/document-title.js +14 -3
- package/dist/helpers/get-preview-file-type.js +22 -3
- package/dist/helpers/get-timeline-max-zoom.d.ts +34 -28
- package/dist/helpers/get-timeline-max-zoom.js +46 -29
- package/dist/helpers/inserted-element-selection.d.ts +2 -1
- package/dist/helpers/install-fiber-sequence-order-observer.d.ts +37 -0
- package/dist/helpers/install-fiber-sequence-order-observer.js +109 -0
- package/dist/helpers/open-in-editor.js +2 -1
- package/dist/helpers/use-menu-structure.js +2 -2
- package/dist/helpers/use-runtime-values.d.ts +1 -1
- package/dist/helpers/use-runtime-values.js +5 -4
- package/dist/helpers/use-sync-external-store.d.ts +3 -0
- package/dist/helpers/use-sync-external-store.js +5 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -1
- package/dist/previewEntry.js +2 -0
- package/dist/state/modals.d.ts +16 -2
- package/dist/state/timeline-sequence-hover.js +3 -2
- package/dist/state/timeline-zoom.d.ts +0 -1
- package/dist/state/timeline-zoom.js +13 -6
- package/package.json +17 -17
- package/dist/helpers/sort-by-nonce-history.d.ts +0 -1
- package/dist/helpers/sort-by-nonce-history.js +0 -6
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description Shuts down the Remotion Studio.
|
|
3
|
+
* @see [Documentation](https://www.remotion.dev/docs/studio/shut-down-studio)
|
|
4
|
+
*/
|
|
5
|
+
import type { ShutdownStudioResponse } from '@remotion/studio-shared';
|
|
6
|
+
export declare const shutDownStudio: () => Promise<ShutdownStudioResponse>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @description Shuts down the Remotion Studio.
|
|
4
|
+
* @see [Documentation](https://www.remotion.dev/docs/studio/shut-down-studio)
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.shutDownStudio = void 0;
|
|
8
|
+
const remotion_1 = require("remotion");
|
|
9
|
+
const call_api_1 = require("../components/call-api");
|
|
10
|
+
const browser_studio_operations_1 = require("../helpers/browser-studio-operations");
|
|
11
|
+
const shutDownStudio = () => {
|
|
12
|
+
if (!(0, remotion_1.getRemotionEnvironment)().isStudio) {
|
|
13
|
+
throw new Error('shutDownStudio() is only available in the Studio');
|
|
14
|
+
}
|
|
15
|
+
if ((0, browser_studio_operations_1.getBrowserStudioOperations)() !== null) {
|
|
16
|
+
throw new Error('shutDownStudio() is not supported in Browser Studio');
|
|
17
|
+
}
|
|
18
|
+
if (window.remotion_isReadOnlyStudio) {
|
|
19
|
+
throw new Error('shutDownStudio() is not available in read-only Studio');
|
|
20
|
+
}
|
|
21
|
+
return (0, call_api_1.callApi)('/api/shutdown-studio', {});
|
|
22
|
+
};
|
|
23
|
+
exports.shutDownStudio = shutDownStudio;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.visualControl = void 0;
|
|
4
|
-
const react_1 = require("react");
|
|
5
4
|
const remotion_1 = require("remotion");
|
|
5
|
+
const use_sync_external_store_1 = require("../helpers/use-sync-external-store");
|
|
6
6
|
const visual_control_store_1 = require("../visual-controls/visual-control-store");
|
|
7
7
|
const VisualControls_1 = require("../visual-controls/VisualControls");
|
|
8
8
|
/**
|
|
@@ -12,7 +12,7 @@ const visualControl = (key, value, schema) => {
|
|
|
12
12
|
// Subscribe to store changes so the calling component
|
|
13
13
|
// re-renders when a visual control value is edited in the sidebar.
|
|
14
14
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
15
|
-
(0,
|
|
15
|
+
(0, use_sync_external_store_1.useSyncExternalStore)(visual_control_store_1.visualControlStore.subscribe, visual_control_store_1.visualControlStore.getSnapshot, visual_control_store_1.visualControlStore.getSnapshot);
|
|
16
16
|
if ((0, remotion_1.getRemotionEnvironment)().isRendering) {
|
|
17
17
|
return value;
|
|
18
18
|
}
|
|
@@ -39,6 +39,7 @@ const timeline_utils_1 = require("@remotion/timeline-utils");
|
|
|
39
39
|
const react_1 = __importStar(require("react"));
|
|
40
40
|
const remotion_1 = require("remotion");
|
|
41
41
|
const colors_1 = require("../helpers/colors");
|
|
42
|
+
const get_timeline_max_zoom_1 = require("../helpers/get-timeline-max-zoom");
|
|
42
43
|
const timeline_layout_1 = require("../helpers/timeline-layout");
|
|
43
44
|
const EMPTY_PEAKS = new Float32Array(0);
|
|
44
45
|
const getContainerStyle = (height) => {
|
|
@@ -49,17 +50,15 @@ const getContainerStyle = (height) => {
|
|
|
49
50
|
position: 'relative',
|
|
50
51
|
width: '100%',
|
|
51
52
|
height,
|
|
53
|
+
overflow: 'hidden',
|
|
52
54
|
};
|
|
53
55
|
};
|
|
54
56
|
const waveformCanvasStyle = {
|
|
55
57
|
pointerEvents: 'none',
|
|
56
|
-
|
|
57
|
-
height: '100%',
|
|
58
|
+
flexShrink: 0,
|
|
58
59
|
};
|
|
59
60
|
const volumeCanvasStyle = {
|
|
60
61
|
position: 'absolute',
|
|
61
|
-
width: '100%',
|
|
62
|
-
height: '100%',
|
|
63
62
|
};
|
|
64
63
|
const parseVolume = (volume) => {
|
|
65
64
|
if (typeof volume === 'number') {
|
|
@@ -74,6 +73,7 @@ const AudioWaveformInner = ({ src, height, startFrom, durationInFrames, displayO
|
|
|
74
73
|
if (vidConf === null) {
|
|
75
74
|
throw new Error('Expected video config');
|
|
76
75
|
}
|
|
76
|
+
const waveformSampleRate = Math.ceil(vidConf.fps * get_timeline_max_zoom_1.TIMELINE_FRAME_WIDTH_AT_MAX_ZOOM);
|
|
77
77
|
const waveformCanvas = (0, react_1.useRef)(null);
|
|
78
78
|
const volumeCanvas = (0, react_1.useRef)(null);
|
|
79
79
|
const shouldRenderVolumeOverlay = doesVolumeChange && typeof volume === 'string';
|
|
@@ -102,10 +102,11 @@ const AudioWaveformInner = ({ src, height, startFrom, durationInFrames, displayO
|
|
|
102
102
|
setError(null);
|
|
103
103
|
return (0, timeline_utils_1.subscribeToWaveformPeaks)({
|
|
104
104
|
src,
|
|
105
|
+
waveformSampleRate,
|
|
105
106
|
onPeaks: (p) => setPeaks(p),
|
|
106
107
|
onError: (err) => setError(err),
|
|
107
108
|
});
|
|
108
|
-
}, [src]);
|
|
109
|
+
}, [src, waveformSampleRate]);
|
|
109
110
|
const portionPeaks = (0, react_1.useMemo)(() => {
|
|
110
111
|
if (!peaks) {
|
|
111
112
|
return null;
|
|
@@ -119,6 +120,7 @@ const AudioWaveformInner = ({ src, height, startFrom, durationInFrames, displayO
|
|
|
119
120
|
peaks,
|
|
120
121
|
playbackRate,
|
|
121
122
|
startFrom,
|
|
123
|
+
waveformSampleRate,
|
|
122
124
|
});
|
|
123
125
|
}, [
|
|
124
126
|
displayDurationInFrames,
|
|
@@ -129,6 +131,7 @@ const AudioWaveformInner = ({ src, height, startFrom, durationInFrames, displayO
|
|
|
129
131
|
playbackRate,
|
|
130
132
|
startFrom,
|
|
131
133
|
vidConf.fps,
|
|
134
|
+
waveformSampleRate,
|
|
132
135
|
]);
|
|
133
136
|
// Drawing must happen in a layout effect: when the timeline zooms, the
|
|
134
137
|
// canvas CSS box resizes in the same commit, and painting the bitmap
|
|
@@ -141,14 +144,17 @@ const AudioWaveformInner = ({ src, height, startFrom, durationInFrames, displayO
|
|
|
141
144
|
const pixelRatio = window.devicePixelRatio;
|
|
142
145
|
const h = Math.ceil(height * pixelRatio);
|
|
143
146
|
const w = Math.ceil(visualizationWidth * pixelRatio);
|
|
147
|
+
const drawingWidth = visualizationWidth * pixelRatio;
|
|
144
148
|
canvasElement.width = w;
|
|
145
149
|
canvasElement.height = h;
|
|
150
|
+
canvasElement.style.width = w / pixelRatio + 'px';
|
|
151
|
+
canvasElement.style.height = h / pixelRatio + 'px';
|
|
146
152
|
(0, timeline_utils_1.drawBars)({
|
|
147
153
|
canvas: canvasElement,
|
|
148
154
|
peaks: portionPeaks !== null && portionPeaks !== void 0 ? portionPeaks : EMPTY_PEAKS,
|
|
149
155
|
color: colors_1.WHITE_ALPHA_60,
|
|
150
156
|
volume: visibleVolume,
|
|
151
|
-
width:
|
|
157
|
+
width: drawingWidth,
|
|
152
158
|
});
|
|
153
159
|
}, [height, portionPeaks, visibleVolume, visualizationWidth]);
|
|
154
160
|
(0, react_1.useLayoutEffect)(() => {
|
|
@@ -162,12 +168,15 @@ const AudioWaveformInner = ({ src, height, startFrom, durationInFrames, displayO
|
|
|
162
168
|
const pixelRatio = window.devicePixelRatio;
|
|
163
169
|
const h = Math.ceil(height * pixelRatio);
|
|
164
170
|
const w = Math.ceil(visualizationWidth * pixelRatio);
|
|
171
|
+
const drawingWidth = visualizationWidth * pixelRatio;
|
|
165
172
|
const context = volumeCanvasElement.getContext('2d');
|
|
166
173
|
if (!context) {
|
|
167
174
|
return;
|
|
168
175
|
}
|
|
169
176
|
volumeCanvasElement.width = w;
|
|
170
177
|
volumeCanvasElement.height = h;
|
|
178
|
+
volumeCanvasElement.style.width = w / pixelRatio + 'px';
|
|
179
|
+
volumeCanvasElement.style.height = h / pixelRatio + 'px';
|
|
171
180
|
context.clearRect(0, 0, w, h);
|
|
172
181
|
if (!Array.isArray(visibleVolume)) {
|
|
173
182
|
return;
|
|
@@ -177,7 +186,7 @@ const AudioWaveformInner = ({ src, height, startFrom, durationInFrames, displayO
|
|
|
177
186
|
visibleVolume.forEach((v, index) => {
|
|
178
187
|
const x = visibleVolume.length <= 1
|
|
179
188
|
? 0
|
|
180
|
-
: (index / (visibleVolume.length - 1)) *
|
|
189
|
+
: (index / (visibleVolume.length - 1)) * drawingWidth;
|
|
181
190
|
const y = (1 - v) * (h - timeline_layout_1.TIMELINE_BORDER * 2 * pixelRatio) + pixelRatio;
|
|
182
191
|
if (index === 0) {
|
|
183
192
|
context.moveTo(x, y);
|
|
@@ -29,6 +29,7 @@ const editor_zoom_gestures_1 = require("../state/editor-zoom-gestures");
|
|
|
29
29
|
const modals_1 = require("../state/modals");
|
|
30
30
|
const call_api_1 = require("./call-api");
|
|
31
31
|
const canvas_capture_drop_1 = require("./canvas-capture-drop");
|
|
32
|
+
const composition_drag_data_1 = require("./composition-drag-data");
|
|
32
33
|
const composition_drop_preview_1 = require("./composition-drop-preview");
|
|
33
34
|
const drop_handler_data_1 = require("./drop-handler-data");
|
|
34
35
|
const EditorGuides_1 = __importDefault(require("./EditorGuides"));
|
|
@@ -37,7 +38,6 @@ const use_is_ruler_visible_1 = require("./EditorRuler/use-is-ruler-visible");
|
|
|
37
38
|
const effect_drag_and_drop_1 = require("./effect-drag-and-drop");
|
|
38
39
|
const element_install_api_1 = require("./element-install-api");
|
|
39
40
|
const element_install_request_1 = require("./element-install-request");
|
|
40
|
-
const ElementInstallConfirmation_1 = require("./ElementInstallConfirmation");
|
|
41
41
|
const handle_drop_1 = require("./handle-drop");
|
|
42
42
|
const import_assets_1 = require("./import-assets");
|
|
43
43
|
const layout_1 = require("./layout");
|
|
@@ -47,7 +47,19 @@ const ResetZoomButton_1 = require("./ResetZoomButton");
|
|
|
47
47
|
const SvgImportDialog_1 = require("./SvgImportDialog");
|
|
48
48
|
const imperative_state_1 = require("./Timeline/imperative-state");
|
|
49
49
|
const use_resolved_stack_1 = require("./Timeline/use-resolved-stack");
|
|
50
|
-
const
|
|
50
|
+
const getCanvasDragPreviewMetadata = (mimeTypes) => {
|
|
51
|
+
var _a, _b, _c;
|
|
52
|
+
const composition = (0, composition_drag_data_1.getCompositionDragPreviewMetadata)(mimeTypes);
|
|
53
|
+
if (composition !== null) {
|
|
54
|
+
return {
|
|
55
|
+
...composition,
|
|
56
|
+
width: (_a = composition.width) !== null && _a !== void 0 ? _a : undefined,
|
|
57
|
+
height: (_b = composition.height) !== null && _b !== void 0 ? _b : undefined,
|
|
58
|
+
durationInFrames: (_c = composition.durationInFrames) !== null && _c !== void 0 ? _c : undefined,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
return studio_protocol_1.StudioProtocolInternals.getDragPreviewMetadata(mimeTypes);
|
|
62
|
+
};
|
|
51
63
|
const getContainerStyle = (editorZoomGestures) => ({
|
|
52
64
|
flex: 1,
|
|
53
65
|
display: 'flex',
|
|
@@ -140,10 +152,8 @@ const Canvas = ({ canvasContent, size }) => {
|
|
|
140
152
|
: null;
|
|
141
153
|
const [isAddingAsset, setIsAddingAsset] = (0, react_1.useState)(false);
|
|
142
154
|
const [compositionDropPreview, setCompositionDropPreview] = (0, react_1.useState)(null);
|
|
143
|
-
const [installingElementName, setInstallingElementName] = (0, react_1.useState)(null);
|
|
144
155
|
const [pendingElementInstallRequests, setPendingElementInstallRequests] = (0, react_1.useState)([]);
|
|
145
156
|
const [activeElementInstallRequest, setActiveElementInstallRequest] = (0, react_1.useState)(null);
|
|
146
|
-
const [elementInstallReview, setElementInstallReview] = (0, react_1.useState)(null);
|
|
147
157
|
const lastFocusedAtRef = (0, react_1.useRef)(typeof document === 'undefined' || document.hasFocus() ? Date.now() : null);
|
|
148
158
|
const [assetResolution, setAssetResolution] = (0, react_1.useState)(null);
|
|
149
159
|
const metadataRequestRef = (0, react_1.useRef)(0);
|
|
@@ -601,16 +611,6 @@ const Canvas = ({ canvasContent, size }) => {
|
|
|
601
611
|
updateElementInstallTarget(event.requestId);
|
|
602
612
|
});
|
|
603
613
|
}, [subscribeToEvent, updateElementInstallTarget]);
|
|
604
|
-
(0, react_1.useEffect)(() => {
|
|
605
|
-
if (installingElementName === null) {
|
|
606
|
-
return;
|
|
607
|
-
}
|
|
608
|
-
const previousTitle = document.title;
|
|
609
|
-
document.title = `📦 Install ${installingElementName} - Remotion Studio`;
|
|
610
|
-
return () => {
|
|
611
|
-
document.title = previousTitle;
|
|
612
|
-
};
|
|
613
|
-
}, [installingElementName]);
|
|
614
614
|
(0, react_1.useEffect)(() => {
|
|
615
615
|
if (previewServerClientId === null) {
|
|
616
616
|
return;
|
|
@@ -623,24 +623,103 @@ const Canvas = ({ canvasContent, size }) => {
|
|
|
623
623
|
(0, element_install_request_1.enqueueElementInstallRequest)(event.request);
|
|
624
624
|
});
|
|
625
625
|
}, [previewServerClientId, subscribeToEvent]);
|
|
626
|
+
(0, react_1.useEffect)(() => {
|
|
627
|
+
const onMessage = (event) => {
|
|
628
|
+
var _a, _b;
|
|
629
|
+
const elementLibrary = document.querySelector('iframe[data-remotion-element-library]');
|
|
630
|
+
if (event.source !== (elementLibrary === null || elementLibrary === void 0 ? void 0 : elementLibrary.contentWindow) ||
|
|
631
|
+
!studio_protocol_1.StudioProtocolInternals.isAllowedStudioProtocolPageOrigin(event.origin)) {
|
|
632
|
+
return;
|
|
633
|
+
}
|
|
634
|
+
const payload = studio_protocol_1.StudioProtocolInternals.parseStudioProtocolIframeInstallRequest(event.data);
|
|
635
|
+
const responsePort = event.ports[0];
|
|
636
|
+
if (payload === null || responsePort === undefined) {
|
|
637
|
+
return;
|
|
638
|
+
}
|
|
639
|
+
const canInstall = canReceiveElementInstallRequest &&
|
|
640
|
+
compositionFile !== null &&
|
|
641
|
+
currentCompositionId !== null &&
|
|
642
|
+
previewServerClientId !== null;
|
|
643
|
+
const request = canInstall
|
|
644
|
+
? {
|
|
645
|
+
clientId: previewServerClientId,
|
|
646
|
+
compositionFile,
|
|
647
|
+
compositionId: currentCompositionId,
|
|
648
|
+
createdAt: Date.now(),
|
|
649
|
+
element: {
|
|
650
|
+
...payload.element,
|
|
651
|
+
durationInFrames: (_a = payload.element.durationInFrames) !== null && _a !== void 0 ? _a : null,
|
|
652
|
+
installationMode: (_b = payload.element.installationMode) !== null && _b !== void 0 ? _b : null,
|
|
653
|
+
},
|
|
654
|
+
from: null,
|
|
655
|
+
id: crypto.randomUUID(),
|
|
656
|
+
position: null,
|
|
657
|
+
source: { origin: event.origin, type: 'studio-protocol' },
|
|
658
|
+
}
|
|
659
|
+
: null;
|
|
660
|
+
const result = canInstall
|
|
661
|
+
? {
|
|
662
|
+
success: true,
|
|
663
|
+
status: 'awaiting-confirmation',
|
|
664
|
+
target: {
|
|
665
|
+
compositionId: currentCompositionId,
|
|
666
|
+
projectName: window.remotion_projectName,
|
|
667
|
+
studioOrigin: window.location.origin,
|
|
668
|
+
studioVersion: window.remotion_version,
|
|
669
|
+
},
|
|
670
|
+
}
|
|
671
|
+
: {
|
|
672
|
+
success: false,
|
|
673
|
+
code: 'no-installable-target',
|
|
674
|
+
message: 'Focus a composition in a Remotion Studio that is not read-only, then try again.',
|
|
675
|
+
};
|
|
676
|
+
const timeout = window.setTimeout(() => responsePort.close(), 1000);
|
|
677
|
+
responsePort.onmessage = () => {
|
|
678
|
+
window.clearTimeout(timeout);
|
|
679
|
+
responsePort.close();
|
|
680
|
+
if (request !== null) {
|
|
681
|
+
(0, element_install_request_1.enqueueElementInstallRequest)(request);
|
|
682
|
+
}
|
|
683
|
+
};
|
|
684
|
+
responsePort.postMessage(result);
|
|
685
|
+
};
|
|
686
|
+
window.addEventListener('message', onMessage);
|
|
687
|
+
return () => window.removeEventListener('message', onMessage);
|
|
688
|
+
}, [
|
|
689
|
+
canReceiveElementInstallRequest,
|
|
690
|
+
compositionFile,
|
|
691
|
+
currentCompositionId,
|
|
692
|
+
previewServerClientId,
|
|
693
|
+
]);
|
|
626
694
|
(0, react_1.useEffect)(() => {
|
|
627
695
|
return (0, element_install_request_1.subscribeToElementInstallRequests)((request) => {
|
|
628
|
-
|
|
696
|
+
var _a, _b;
|
|
697
|
+
const isDragAndDrop = request.source.type === 'drag-and-drop';
|
|
698
|
+
const requestWithDefaults = isDragAndDrop
|
|
629
699
|
? request
|
|
630
700
|
: {
|
|
631
701
|
...request,
|
|
632
|
-
from: (0, import_assets_1.getFromForDrop)({
|
|
702
|
+
from: (_a = request.from) !== null && _a !== void 0 ? _a : (0, import_assets_1.getFromForDrop)({
|
|
633
703
|
durationInFrames: request.element.durationInFrames,
|
|
634
704
|
from: (0, imperative_state_1.getCurrentFrame)(),
|
|
635
705
|
preferCompositionStart: true,
|
|
636
706
|
}),
|
|
707
|
+
position: (_b = request.position) !== null && _b !== void 0 ? _b : (0, import_assets_1.getElementPositionForDrop)({
|
|
708
|
+
dimensions: request.element.dimensions,
|
|
709
|
+
dropPosition: contentDimensions === null || contentDimensions === 'none'
|
|
710
|
+
? null
|
|
711
|
+
: {
|
|
712
|
+
centerX: contentDimensions.width / 2,
|
|
713
|
+
centerY: contentDimensions.height / 2,
|
|
714
|
+
},
|
|
715
|
+
}),
|
|
637
716
|
};
|
|
638
717
|
setPendingElementInstallRequests((requests) => [
|
|
639
718
|
...requests,
|
|
640
|
-
|
|
719
|
+
requestWithDefaults,
|
|
641
720
|
]);
|
|
642
721
|
});
|
|
643
|
-
}, []);
|
|
722
|
+
}, [contentDimensions]);
|
|
644
723
|
(0, react_1.useEffect)(() => {
|
|
645
724
|
var _a;
|
|
646
725
|
var _b;
|
|
@@ -680,6 +759,10 @@ const Canvas = ({ canvasContent, size }) => {
|
|
|
680
759
|
setActiveElementInstallRequest(nextRequest);
|
|
681
760
|
setPendingElementInstallRequests(remainingRequests);
|
|
682
761
|
}, [activeElementInstallRequest, pendingElementInstallRequests]);
|
|
762
|
+
const closeElementInstallDialog = (0, react_1.useCallback)(() => {
|
|
763
|
+
setSelectedModal(null);
|
|
764
|
+
setActiveElementInstallRequest(null);
|
|
765
|
+
}, [setSelectedModal]);
|
|
683
766
|
(0, react_1.useEffect)(() => {
|
|
684
767
|
if (activeElementInstallRequest === null) {
|
|
685
768
|
return;
|
|
@@ -687,7 +770,6 @@ const Canvas = ({ canvasContent, size }) => {
|
|
|
687
770
|
let canceled = false;
|
|
688
771
|
const handleInstallRequest = async () => {
|
|
689
772
|
var _a;
|
|
690
|
-
setInstallingElementName(activeElementInstallRequest.element.displayName);
|
|
691
773
|
try {
|
|
692
774
|
const [newPreflight, currentPreflight] = await Promise.all([
|
|
693
775
|
(0, element_install_api_1.prepareElementInstall)({
|
|
@@ -711,17 +793,11 @@ const Canvas = ({ canvasContent, size }) => {
|
|
|
711
793
|
}
|
|
712
794
|
if (!newPreflight.success) {
|
|
713
795
|
(0, NotificationCenter_1.showNotification)(`Could not review Element installation: ${newPreflight.reason}`, 4000);
|
|
714
|
-
setInstallingElementName(null);
|
|
715
796
|
setActiveElementInstallRequest(null);
|
|
716
797
|
return;
|
|
717
798
|
}
|
|
718
799
|
const declaredDependencies = Array.from(new Map(activeElementInstallRequest.element.dependencies.map((dependency) => [dependency.name, dependency])).values());
|
|
719
|
-
const missingPackages = (0, install_required_package_1.getMissingPackages)(declaredDependencies).map((dependency) => dependency.
|
|
720
|
-
const ignoredDependencies = declaredDependencies.filter((dependency) => elementInstallDependencyIgnoreList.includes(dependency.name) &&
|
|
721
|
-
!missingPackages.includes(dependency.name));
|
|
722
|
-
const dependenciesToReview = declaredDependencies
|
|
723
|
-
.filter((dependency) => !ignoredDependencies.includes(dependency))
|
|
724
|
-
.map((dependency) => dependency.version === null
|
|
800
|
+
const missingPackages = (0, install_required_package_1.getMissingPackages)(declaredDependencies).map((dependency) => dependency.version === null
|
|
725
801
|
? dependency.name
|
|
726
802
|
: `${dependency.name}@${dependency.version}`);
|
|
727
803
|
const { source } = activeElementInstallRequest;
|
|
@@ -735,12 +811,13 @@ const Canvas = ({ canvasContent, size }) => {
|
|
|
735
811
|
const currentPlan = currentPreflight.success
|
|
736
812
|
? currentPreflight.plan
|
|
737
813
|
: null;
|
|
738
|
-
setSelectedModal(
|
|
739
|
-
|
|
814
|
+
setSelectedModal({
|
|
815
|
+
type: 'element-install',
|
|
740
816
|
currentPlan,
|
|
741
|
-
dependenciesToReview,
|
|
742
817
|
missingPackages,
|
|
743
818
|
newPlan: newPreflight.plan,
|
|
819
|
+
onClose: closeElementInstallDialog,
|
|
820
|
+
request: activeElementInstallRequest,
|
|
744
821
|
sourceIsUnverified,
|
|
745
822
|
sourceLabel,
|
|
746
823
|
});
|
|
@@ -750,7 +827,6 @@ const Canvas = ({ canvasContent, size }) => {
|
|
|
750
827
|
return;
|
|
751
828
|
}
|
|
752
829
|
(0, NotificationCenter_1.showNotification)(`Could not review Element installation: ${error instanceof Error ? error.message : String(error)}`, 4000);
|
|
753
|
-
setInstallingElementName(null);
|
|
754
830
|
setActiveElementInstallRequest(null);
|
|
755
831
|
}
|
|
756
832
|
};
|
|
@@ -758,12 +834,11 @@ const Canvas = ({ canvasContent, size }) => {
|
|
|
758
834
|
return () => {
|
|
759
835
|
canceled = true;
|
|
760
836
|
};
|
|
761
|
-
}, [
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
}, []);
|
|
837
|
+
}, [
|
|
838
|
+
activeElementInstallRequest,
|
|
839
|
+
closeElementInstallDialog,
|
|
840
|
+
setSelectedModal,
|
|
841
|
+
]);
|
|
767
842
|
const onDragOver = (0, react_1.useCallback)((event) => {
|
|
768
843
|
var _a;
|
|
769
844
|
var _b;
|
|
@@ -787,7 +862,7 @@ const Canvas = ({ canvasContent, size }) => {
|
|
|
787
862
|
setCompositionDropPreview(null);
|
|
788
863
|
return;
|
|
789
864
|
}
|
|
790
|
-
const metadata =
|
|
865
|
+
const metadata = getCanvasDragPreviewMetadata((_b = (_a = event.dataTransfer) === null || _a === void 0 ? void 0 : _a.types) !== null && _b !== void 0 ? _b : []);
|
|
791
866
|
if (((metadata === null || metadata === void 0 ? void 0 : metadata.type) !== 'composition' && (metadata === null || metadata === void 0 ? void 0 : metadata.type) !== 'element') ||
|
|
792
867
|
metadata.width === undefined ||
|
|
793
868
|
metadata.height === undefined) {
|
|
@@ -918,7 +993,7 @@ const Canvas = ({ canvasContent, size }) => {
|
|
|
918
993
|
event.stopPropagation();
|
|
919
994
|
setIsAddingAsset(true);
|
|
920
995
|
try {
|
|
921
|
-
const metadata =
|
|
996
|
+
const metadata = getCanvasDragPreviewMetadata((_d = (_b = event.dataTransfer) === null || _b === void 0 ? void 0 : _b.types) !== null && _d !== void 0 ? _d : []);
|
|
922
997
|
const isComposition = (metadata === null || metadata === void 0 ? void 0 : metadata.type) === 'composition';
|
|
923
998
|
let dropPosition = getDropPosition({
|
|
924
999
|
addFitPadding,
|
|
@@ -1122,15 +1197,6 @@ const Canvas = ({ canvasContent, size }) => {
|
|
|
1122
1197
|
};
|
|
1123
1198
|
}, [compositionDropPreview, contentDimensions, previewSize, size]);
|
|
1124
1199
|
return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
|
|
1125
|
-
jsx_runtime_1.jsxs("div", { ref: canvas_ref_1.canvasRef, style: getContainerStyle(editorZoomGestures), children: [size ? (jsx_runtime_1.jsx(Preview_1.VideoPreview, { canvasContent: canvasContent, contentDimensions: contentDimensions, canvasSize: size, assetMetadata: assetResolution, onRetryAssetMetadata: fetchMetadata })) : null, compositionDropPreviewStyle === null ? null : (jsx_runtime_1.jsx("div", { className: "css-reset", "data-testid": "composition-drop-preview", style: compositionDropPreviewStyle })), isFit ? null : (jsx_runtime_1.jsx("div", { style: resetZoom, className: "css-reset", children: jsx_runtime_1.jsx(ResetZoomButton_1.ResetZoomButton, { onClick: onReset }) })), editorShowGuides && canvasContent.type === 'composition' && (jsx_runtime_1.jsx(EditorGuides_1.default, { canvasSize: size, contentDimensions: contentDimensions, assetMetadata: assetResolution }))] }), areRulersVisible && (jsx_runtime_1.jsx(EditorRuler_1.EditorRulers, { canCreateGuides: canvasContent.type === 'composition', contentDimensions: contentDimensions, canvasSize: size, assetMetadata: assetResolution, containerRef: canvas_ref_1.canvasRef }))
|
|
1126
|
-
elementInstallReview === null ? null : (jsx_runtime_1.jsx(ElementInstallConfirmation_1.ElementInstallConfirmation, { currentCompositionMetadata: config === null ||
|
|
1127
|
-
currentCompositionId !== activeElementInstallRequest.compositionId
|
|
1128
|
-
? null
|
|
1129
|
-
: {
|
|
1130
|
-
durationInFrames: config.durationInFrames,
|
|
1131
|
-
fps: config.fps,
|
|
1132
|
-
height: config.height,
|
|
1133
|
-
width: config.width,
|
|
1134
|
-
}, currentPlan: elementInstallReview.currentPlan, dependenciesToReview: elementInstallReview.dependenciesToReview, missingPackages: elementInstallReview.missingPackages, newPlan: elementInstallReview.newPlan, onClose: closeElementInstallDialog, request: activeElementInstallRequest, sourceIsUnverified: elementInstallReview.sourceIsUnverified, sourceLabel: elementInstallReview.sourceLabel, usesBrowserDependencyResolution: (0, browser_studio_operations_1.getBrowserStudioOperations)() !== null }))] }));
|
|
1200
|
+
jsx_runtime_1.jsxs("div", { ref: canvas_ref_1.canvasRef, style: getContainerStyle(editorZoomGestures), children: [size ? (jsx_runtime_1.jsx(Preview_1.VideoPreview, { canvasContent: canvasContent, contentDimensions: contentDimensions, canvasSize: size, assetMetadata: assetResolution, onRetryAssetMetadata: fetchMetadata })) : null, compositionDropPreviewStyle === null ? null : (jsx_runtime_1.jsx("div", { className: "css-reset", "data-testid": "composition-drop-preview", style: compositionDropPreviewStyle })), isFit ? null : (jsx_runtime_1.jsx("div", { style: resetZoom, className: "css-reset", children: jsx_runtime_1.jsx(ResetZoomButton_1.ResetZoomButton, { onClick: onReset }) })), editorShowGuides && canvasContent.type === 'composition' && (jsx_runtime_1.jsx(EditorGuides_1.default, { canvasSize: size, contentDimensions: contentDimensions, assetMetadata: assetResolution }))] }), areRulersVisible && (jsx_runtime_1.jsx(EditorRuler_1.EditorRulers, { canCreateGuides: canvasContent.type === 'composition', contentDimensions: contentDimensions, canvasSize: size, assetMetadata: assetResolution, containerRef: canvas_ref_1.canvasRef }))] }));
|
|
1135
1201
|
};
|
|
1136
1202
|
exports.Canvas = Canvas;
|
|
@@ -6,6 +6,7 @@ export declare const CaptionInspector: React.FC<{
|
|
|
6
6
|
readonly onTextChange: (captions: Caption[]) => void;
|
|
7
7
|
readonly onTextSave: ((captions: Caption[]) => void) | null;
|
|
8
8
|
readonly onTextCancel: (() => void) | null;
|
|
9
|
+
readonly onReplaceCaptions: ((captions: Caption[]) => void) | null;
|
|
9
10
|
readonly onToggle: () => void;
|
|
10
11
|
readonly readOnly: boolean;
|
|
11
12
|
readonly readOnlyTitle: string | null;
|
|
@@ -2,11 +2,19 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.CaptionInspector = void 0;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_1 = require("react");
|
|
5
6
|
const colors_1 = require("../helpers/colors");
|
|
7
|
+
const upload_1 = require("../icons/upload");
|
|
8
|
+
const Button_1 = require("./Button");
|
|
6
9
|
const CaptionTextEditor_1 = require("./CaptionTextEditor");
|
|
7
10
|
const CollapsibleInspectorSectionHeader_1 = require("./InspectorPanel/CollapsibleInspectorSectionHeader");
|
|
8
11
|
const common_1 = require("./InspectorPanel/common");
|
|
9
12
|
const styles_1 = require("./InspectorPanel/styles");
|
|
13
|
+
const NotificationCenter_1 = require("./Notifications/NotificationCenter");
|
|
14
|
+
const parse_caption_file_1 = require("./parse-caption-file");
|
|
15
|
+
const importTooltip = `Import captions
|
|
16
|
+
|
|
17
|
+
Supports Remotion Caption[] JSON. Files are processed locally.`;
|
|
10
18
|
const readOnlyStatus = {
|
|
11
19
|
color: colors_1.LIGHT_TEXT,
|
|
12
20
|
fontFamily: 'sans-serif',
|
|
@@ -15,8 +23,41 @@ const readOnlyStatus = {
|
|
|
15
23
|
lineHeight: '16px',
|
|
16
24
|
marginLeft: 12,
|
|
17
25
|
};
|
|
18
|
-
const CaptionInspector = ({ captions, expanded, onTextChange, onTextSave, onTextCancel, onToggle, readOnly, readOnlyTitle, }) => {
|
|
26
|
+
const CaptionInspector = ({ captions, expanded, onTextChange, onTextSave, onTextCancel, onReplaceCaptions, onToggle, readOnly, readOnlyTitle, }) => {
|
|
27
|
+
const fileInput = (0, react_1.useRef)(null);
|
|
28
|
+
const [isImporting, setIsImporting] = (0, react_1.useState)(false);
|
|
29
|
+
const importCaptions = (0, react_1.useCallback)(async (event) => {
|
|
30
|
+
var _a;
|
|
31
|
+
const file = (_a = event.currentTarget.files) === null || _a === void 0 ? void 0 : _a[0];
|
|
32
|
+
event.currentTarget.value = '';
|
|
33
|
+
if (!file || onReplaceCaptions === null) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
setIsImporting(true);
|
|
37
|
+
try {
|
|
38
|
+
onReplaceCaptions((0, parse_caption_file_1.parseCaptionFile)({
|
|
39
|
+
fileName: file.name,
|
|
40
|
+
contents: await file.text(),
|
|
41
|
+
}));
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
(0, NotificationCenter_1.showNotification)(`Could not import ${file.name}: ${error instanceof Error ? error.message : String(error)}`, 5000);
|
|
45
|
+
}
|
|
46
|
+
finally {
|
|
47
|
+
setIsImporting(false);
|
|
48
|
+
}
|
|
49
|
+
}, [onReplaceCaptions]);
|
|
19
50
|
return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
|
|
20
|
-
jsx_runtime_1.jsx(common_1.InspectorSectionHeader, { children: jsx_runtime_1.jsx(CollapsibleInspectorSectionHeader_1.CollapsibleInspectorSectionHeader, { action: jsx_runtime_1.
|
|
51
|
+
jsx_runtime_1.jsx(common_1.InspectorSectionHeader, { children: jsx_runtime_1.jsx(CollapsibleInspectorSectionHeader_1.CollapsibleInspectorSectionHeader, { action: jsx_runtime_1.jsxs("div", { style: styles_1.sectionHeaderEnd, children: [onReplaceCaptions === null ? null : (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
|
|
52
|
+
jsx_runtime_1.jsx("input", { ref: fileInput, accept: ".json", "aria-label": "Import captions file", hidden: true, onChange: importCaptions, type: "file" }), jsx_runtime_1.jsxs(Button_1.Button, { buttonContainerStyle: {
|
|
53
|
+
alignItems: 'center',
|
|
54
|
+
display: 'flex',
|
|
55
|
+
gap: 4,
|
|
56
|
+
}, disabled: isImporting, onClick: () => {
|
|
57
|
+
var _a;
|
|
58
|
+
return (_a = fileInput.current) === null || _a === void 0 ? void 0 : _a.click();
|
|
59
|
+
}, size: "condensed", title: importTooltip, children: [
|
|
60
|
+
jsx_runtime_1.jsx(upload_1.UploadIcon, { "aria-hidden": "true", color: colors_1.CURRENT_COLOR, focusable: "false", style: { height: 12, width: 12 } }), isImporting ? 'Importing…' : 'Import'] })
|
|
61
|
+
] })), readOnly ? (jsx_runtime_1.jsx("div", { style: readOnlyStatus, title: readOnlyTitle !== null && readOnlyTitle !== void 0 ? readOnlyTitle : undefined, children: "Read only" })) : null] }), expanded: expanded, label: "Captions", onToggle: onToggle }) }), expanded ? (jsx_runtime_1.jsx(CaptionTextEditor_1.CaptionTextEditor, { captions: captions, onChange: onTextChange, onSave: onTextSave, onCancel: onTextCancel, readOnly: readOnly })) : null] }));
|
|
21
62
|
};
|
|
22
63
|
exports.CaptionInspector = CaptionInspector;
|
|
@@ -119,7 +119,7 @@ const CaptionTextEditor = ({ captions, onChange, onSave, onCancel, readOnly }) =
|
|
|
119
119
|
? `Remove page break after caption ${index + 1}`
|
|
120
120
|
: `Add page break after caption ${index + 1}`;
|
|
121
121
|
return (jsx_runtime_1.jsxs("div", { style: row, children: [
|
|
122
|
-
jsx_runtime_1.jsxs("div", { style: timing, children: [formatMilliseconds(caption.startMs), " \u2192", ' ', formatMilliseconds(caption.endMs), " ms"] }), jsx_runtime_1.jsx(RemInput_1.RemotionInput, { "data-caption-index": index, disabled: readOnly, onBlur: (event) => {
|
|
122
|
+
jsx_runtime_1.jsxs("div", { style: timing, children: [formatMilliseconds(caption.startMs), " \u2192", ' ', formatMilliseconds(caption.endMs), " ms"] }), jsx_runtime_1.jsx(RemInput_1.RemotionInput, { "aria-label": `Caption ${index + 1}`, "data-caption-index": index, disabled: readOnly, onBlur: (event) => {
|
|
123
123
|
if (cancelledBlurIndexes.current.delete(index)) {
|
|
124
124
|
return;
|
|
125
125
|
}
|