@remotion/studio 4.0.445 → 4.0.447
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 +1 -1
- 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/NewComposition/MenuContent.js +58 -0
- package/dist/components/NewComposition/menu-typeahead.d.ts +5 -0
- package/dist/components/NewComposition/menu-typeahead.js +27 -0
- package/dist/components/Preview.d.ts +1 -0
- package/dist/components/Preview.js +14 -1
- package/dist/components/RenderButton.js +1 -0
- package/dist/components/RenderModal/OptionExplainer.js +10 -2
- package/dist/components/RenderModal/WebRenderModal.js +6 -2
- package/dist/components/RenderModal/WebRenderModalAdvanced.d.ts +2 -0
- package/dist/components/RenderModal/WebRenderModalAdvanced.js +10 -2
- package/dist/components/RenderQueue/ClientRenderQueueProcessor.js +4 -3
- package/dist/components/RenderQueue/client-side-render-types.d.ts +1 -0
- package/dist/components/Timeline/TimelineListItem.js +53 -2
- 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-bqd9dhnk.js → chunk-ase93hmz.js} +4588 -4229
- package/dist/esm/internals.mjs +4588 -4229
- package/dist/esm/previewEntry.mjs +542 -185
- 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/retry-payload.js +1 -0
- 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/modals.d.ts +1 -0
- package/package.json +9 -9
|
@@ -44,6 +44,7 @@ const no_react_1 = require("remotion/no-react");
|
|
|
44
44
|
const colors_1 = require("../helpers/colors");
|
|
45
45
|
const copy_text_1 = require("../helpers/copy-text");
|
|
46
46
|
const mobile_layout_1 = require("../helpers/mobile-layout");
|
|
47
|
+
const sidebar_scroll_into_view_1 = require("../helpers/sidebar-scroll-into-view");
|
|
47
48
|
const url_state_1 = require("../helpers/url-state");
|
|
48
49
|
const use_asset_drag_events_1 = __importDefault(require("../helpers/use-asset-drag-events"));
|
|
49
50
|
const clipboard_1 = require("../icons/clipboard");
|
|
@@ -173,7 +174,16 @@ const AssetSelectorItem = ({ item, tabIndex, level, parentFolder, readOnlyStudio
|
|
|
173
174
|
const onPointerLeave = (0, react_1.useCallback)(() => {
|
|
174
175
|
setHovered(false);
|
|
175
176
|
}, []);
|
|
177
|
+
const rowRef = (0, react_1.useRef)(null);
|
|
178
|
+
(0, react_1.useLayoutEffect)(() => {
|
|
179
|
+
(0, sidebar_scroll_into_view_1.maybeScrollAssetSidebarRowIntoView)({
|
|
180
|
+
element: rowRef.current,
|
|
181
|
+
assetPath: relativePath,
|
|
182
|
+
selected,
|
|
183
|
+
});
|
|
184
|
+
}, [relativePath, selected]);
|
|
176
185
|
const onClick = (0, react_1.useCallback)(() => {
|
|
186
|
+
(0, sidebar_scroll_into_view_1.markAssetSidebarScrollFromRowClick)(relativePath);
|
|
177
187
|
setCanvasContent({ type: 'asset', asset: relativePath });
|
|
178
188
|
(0, url_state_1.pushUrl)(`/assets/${relativePath}`);
|
|
179
189
|
if (isMobileLayout) {
|
|
@@ -234,7 +244,7 @@ const AssetSelectorItem = ({ item, tabIndex, level, parentFolder, readOnlyStudio
|
|
|
234
244
|
(0, NotificationCenter_1.showNotification)(`Could not copy: ${err.message}`, 2000);
|
|
235
245
|
});
|
|
236
246
|
}, [item.name, parentFolder]);
|
|
237
|
-
return (jsx_runtime_1.jsx(layout_1.Row, { align: "center", children: jsx_runtime_1.jsxs("div", { style: style, onPointerEnter: onPointerEnter, onPointerLeave: onPointerLeave, onClick: onClick, tabIndex: tabIndex, title: item.name, children: [
|
|
247
|
+
return (jsx_runtime_1.jsx(layout_1.Row, { align: "center", children: jsx_runtime_1.jsxs("div", { ref: rowRef, style: style, onPointerEnter: onPointerEnter, onPointerLeave: onPointerLeave, onClick: onClick, tabIndex: tabIndex, title: item.name, children: [
|
|
238
248
|
jsx_runtime_1.jsx(file_1.FileIcon, { style: iconStyle, color: colors_1.LIGHT_TEXT }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 1 }), jsx_runtime_1.jsx("div", { style: label, children: item.name }), hovered ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
|
|
239
249
|
jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(InlineAction_1.InlineAction, { title: "Copy staticFile() name", renderAction: renderCopyAction, onClick: copyToClipboard }), readOnlyStudio ? null : (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
|
|
240
250
|
jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(InlineAction_1.InlineAction, { title: "Open in Explorer", renderAction: renderFileExplorerAction, onClick: revealInExplorer })
|
|
@@ -418,6 +418,6 @@ const Canvas = ({ canvasContent, size }) => {
|
|
|
418
418
|
fetchMetadata();
|
|
419
419
|
}, [fetchMetadata]);
|
|
420
420
|
return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
|
|
421
|
-
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 })) : null, 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, { contentDimensions: contentDimensions, canvasSize: size, assetMetadata: assetResolution, containerRef: canvas_ref_1.canvasRef }))] }));
|
|
421
|
+
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, 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, { contentDimensions: contentDimensions, canvasSize: size, assetMetadata: assetResolution, containerRef: canvas_ref_1.canvasRef }))] }));
|
|
422
422
|
};
|
|
423
423
|
exports.Canvas = Canvas;
|
|
@@ -45,7 +45,7 @@ const CanvasOrLoading = ({ size }) => {
|
|
|
45
45
|
});
|
|
46
46
|
}, [resolved, setZoom]);
|
|
47
47
|
if (renderError) {
|
|
48
|
-
return jsx_runtime_1.jsx(ErrorLoading, { error: renderError });
|
|
48
|
+
return (jsx_runtime_1.jsx(ErrorLoading, { error: renderError, calculateMetadataContext: false }));
|
|
49
49
|
}
|
|
50
50
|
if (!canvasContent) {
|
|
51
51
|
const compname = window.location.pathname.replace('/', '');
|
|
@@ -65,7 +65,7 @@ const CanvasOrLoading = ({ size }) => {
|
|
|
65
65
|
return (jsx_runtime_1.jsx("div", { style: container, className: "css-reset", children: jsx_runtime_1.jsx(RunningCalculateMetadata_1.RunningCalculateMetadata, {}) }));
|
|
66
66
|
}
|
|
67
67
|
if (resolved.type === 'error') {
|
|
68
|
-
return jsx_runtime_1.jsx(ErrorLoading, { error: resolved.error });
|
|
68
|
+
return jsx_runtime_1.jsx(ErrorLoading, { error: resolved.error, calculateMetadataContext: true });
|
|
69
69
|
}
|
|
70
70
|
return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
|
|
71
71
|
jsx_runtime_1.jsx(FramePersistor_1.FramePersistor, {}),
|
|
@@ -80,9 +80,9 @@ const loaderContainer = {
|
|
|
80
80
|
height: '100%',
|
|
81
81
|
overflowY: 'auto',
|
|
82
82
|
};
|
|
83
|
-
const ErrorLoading = ({ error }) => {
|
|
83
|
+
const ErrorLoading = ({ error, calculateMetadataContext }) => {
|
|
84
84
|
return (jsx_runtime_1.jsx("div", { style: loaderContainer, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: jsx_runtime_1.jsx(ErrorLoader_1.ErrorLoader, { canHaveDismissButton: false, keyboardShortcuts: false, error: error, onRetry: () => {
|
|
85
85
|
var _a;
|
|
86
86
|
return (_a = remotion_1.Internals.resolveCompositionsRef.current) === null || _a === void 0 ? void 0 : _a.reloadCurrentlySelectedComposition();
|
|
87
|
-
}, calculateMetadata:
|
|
87
|
+
}, calculateMetadata: calculateMetadataContext }, error.stack) }));
|
|
88
88
|
};
|
|
@@ -5,6 +5,7 @@ const jsx_runtime_1 = require("react/jsx-runtime");
|
|
|
5
5
|
const react_1 = require("react");
|
|
6
6
|
const colors_1 = require("../helpers/colors");
|
|
7
7
|
const is_composition_still_1 = require("../helpers/is-composition-still");
|
|
8
|
+
const sidebar_scroll_into_view_1 = require("../helpers/sidebar-scroll-into-view");
|
|
8
9
|
const folder_1 = require("../icons/folder");
|
|
9
10
|
const still_1 = require("../icons/still");
|
|
10
11
|
const video_1 = require("../icons/video");
|
|
@@ -61,6 +62,18 @@ const CompositionSelectorItem = ({ item, level, currentComposition, tabIndex, se
|
|
|
61
62
|
const onPointerLeave = (0, react_1.useCallback)(() => {
|
|
62
63
|
setHovered(false);
|
|
63
64
|
}, []);
|
|
65
|
+
const compositionRowRef = (0, react_1.useRef)(null);
|
|
66
|
+
const compositionId = item.type === 'composition' ? item.composition.id : null;
|
|
67
|
+
(0, react_1.useLayoutEffect)(() => {
|
|
68
|
+
if (compositionId === null) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
(0, sidebar_scroll_into_view_1.maybeScrollCompositionSidebarRowIntoView)({
|
|
72
|
+
element: compositionRowRef.current,
|
|
73
|
+
compositionId,
|
|
74
|
+
selected,
|
|
75
|
+
});
|
|
76
|
+
}, [compositionId, selected]);
|
|
64
77
|
const style = (0, react_1.useMemo)(() => {
|
|
65
78
|
return {
|
|
66
79
|
...itemStyle,
|
|
@@ -77,6 +90,7 @@ const CompositionSelectorItem = ({ item, level, currentComposition, tabIndex, se
|
|
|
77
90
|
const onClick = (0, react_1.useCallback)((evt) => {
|
|
78
91
|
evt.preventDefault();
|
|
79
92
|
if (item.type === 'composition') {
|
|
93
|
+
(0, sidebar_scroll_into_view_1.markCompositionSidebarScrollFromRowClick)(item.composition.id);
|
|
80
94
|
selectComposition(item.composition, true);
|
|
81
95
|
}
|
|
82
96
|
else {
|
|
@@ -180,7 +194,7 @@ const CompositionSelectorItem = ({ item, level, currentComposition, tabIndex, se
|
|
|
180
194
|
})
|
|
181
195
|
: null] }));
|
|
182
196
|
}
|
|
183
|
-
return (jsx_runtime_1.jsx(ContextMenu_1.ContextMenu, { values: contextMenu, children: jsx_runtime_1.jsx(layout_1.Row, { align: "center", children: jsx_runtime_1.jsxs("a", { style: style, onPointerEnter: onPointerEnter, onPointerLeave: onPointerLeave, tabIndex: tabIndex, onClick: onClick, onKeyPress: onKeyPress, type: "button", title: item.composition.id, className: "__remotion-composition", "data-compname": item.composition.id, children: [(0, is_composition_still_1.isCompositionStill)(item.composition) ? (jsx_runtime_1.jsx(still_1.StillIcon, { color: hovered || selected ? 'white' : colors_1.LIGHT_TEXT, style: iconStyle })) : (jsx_runtime_1.jsx(video_1.FilmIcon, { color: hovered || selected ? 'white' : colors_1.LIGHT_TEXT, style: iconStyle })), jsx_runtime_1.jsx(layout_1.Spacing, { x: 1 }), jsx_runtime_1.jsx("div", { style: label, children: item.composition.id }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(CompositionContextButton_1.CompositionContextButton, { values: contextMenu, visible: hovered }), jsx_runtime_1.jsx(SidebarRenderButton_1.SidebarRenderButton, { visible: hovered, composition: item.composition })
|
|
197
|
+
return (jsx_runtime_1.jsx(ContextMenu_1.ContextMenu, { values: contextMenu, children: jsx_runtime_1.jsx(layout_1.Row, { align: "center", children: jsx_runtime_1.jsxs("a", { ref: compositionRowRef, style: style, onPointerEnter: onPointerEnter, onPointerLeave: onPointerLeave, tabIndex: tabIndex, onClick: onClick, onKeyPress: onKeyPress, type: "button", title: item.composition.id, className: "__remotion-composition", "data-compname": item.composition.id, children: [(0, is_composition_still_1.isCompositionStill)(item.composition) ? (jsx_runtime_1.jsx(still_1.StillIcon, { color: hovered || selected ? 'white' : colors_1.LIGHT_TEXT, style: iconStyle })) : (jsx_runtime_1.jsx(video_1.FilmIcon, { color: hovered || selected ? 'white' : colors_1.LIGHT_TEXT, style: iconStyle })), jsx_runtime_1.jsx(layout_1.Spacing, { x: 1 }), jsx_runtime_1.jsx("div", { style: label, children: item.composition.id }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(CompositionContextButton_1.CompositionContextButton, { values: contextMenu, visible: hovered }), jsx_runtime_1.jsx(SidebarRenderButton_1.SidebarRenderButton, { visible: hovered, composition: item.composition })
|
|
184
198
|
] }) }) }));
|
|
185
199
|
};
|
|
186
200
|
exports.CompositionSelectorItem = CompositionSelectorItem;
|
|
@@ -20,6 +20,9 @@ const FilePreview = ({ fileType, src, currentAsset, assetMetadata }) => {
|
|
|
20
20
|
if (assetMetadata.type === 'not-found') {
|
|
21
21
|
throw new Error('expected to have assetMetadata, got "not-found"');
|
|
22
22
|
}
|
|
23
|
+
if (assetMetadata.type === 'metadata-error') {
|
|
24
|
+
throw new Error('unexpected metadata-error in FilePreview');
|
|
25
|
+
}
|
|
23
26
|
if (fileType === 'audio') {
|
|
24
27
|
return jsx_runtime_1.jsx("audio", { src: src, controls: true });
|
|
25
28
|
}
|
|
@@ -14,7 +14,7 @@ const use_static_files_1 = require("./use-static-files");
|
|
|
14
14
|
const useSelectAsset = () => {
|
|
15
15
|
const { setCanvasContent } = (0, react_1.useContext)(remotion_1.Internals.CompositionSetters);
|
|
16
16
|
const { setAssetFoldersExpanded } = (0, react_1.useContext)(folders_1.FolderContext);
|
|
17
|
-
return (asset) => {
|
|
17
|
+
return (0, react_1.useCallback)((asset) => {
|
|
18
18
|
var _a;
|
|
19
19
|
setCanvasContent({ type: 'asset', asset });
|
|
20
20
|
(_a = ExplorerPanel_1.explorerSidebarTabs.current) === null || _a === void 0 ? void 0 : _a.selectAssetsPanel();
|
|
@@ -31,7 +31,7 @@ const useSelectAsset = () => {
|
|
|
31
31
|
}
|
|
32
32
|
return newState;
|
|
33
33
|
});
|
|
34
|
-
};
|
|
34
|
+
}, [setAssetFoldersExpanded, setCanvasContent]);
|
|
35
35
|
};
|
|
36
36
|
exports.useSelectAsset = useSelectAsset;
|
|
37
37
|
const useSelectComposition = () => {
|
|
@@ -134,7 +134,7 @@ const InitialCompositionLoader = () => {
|
|
|
134
134
|
return file.name === newCanvas.asset;
|
|
135
135
|
});
|
|
136
136
|
if (exists) {
|
|
137
|
-
|
|
137
|
+
selectAsset(newCanvas.asset);
|
|
138
138
|
}
|
|
139
139
|
return;
|
|
140
140
|
}
|
|
@@ -142,7 +142,13 @@ const InitialCompositionLoader = () => {
|
|
|
142
142
|
};
|
|
143
143
|
window.addEventListener('popstate', onchange);
|
|
144
144
|
return () => window.removeEventListener('popstate', onchange);
|
|
145
|
-
}, [
|
|
145
|
+
}, [
|
|
146
|
+
compositions,
|
|
147
|
+
selectAsset,
|
|
148
|
+
selectComposition,
|
|
149
|
+
setCanvasContent,
|
|
150
|
+
staticFiles,
|
|
151
|
+
]);
|
|
146
152
|
return null;
|
|
147
153
|
};
|
|
148
154
|
exports.InitialCompositionLoader = InitialCompositionLoader;
|
|
@@ -10,6 +10,7 @@ const is_menu_item_1 = require("../Menu/is-menu-item");
|
|
|
10
10
|
const MenuDivider_1 = require("../Menu/MenuDivider");
|
|
11
11
|
const MenuSubItem_1 = require("../Menu/MenuSubItem");
|
|
12
12
|
const styles_1 = require("../Menu/styles");
|
|
13
|
+
const menu_typeahead_1 = require("./menu-typeahead");
|
|
13
14
|
const BORDER_SIZE = 1;
|
|
14
15
|
const container = {
|
|
15
16
|
paddingTop: styles_1.MENU_VERTICAL_PADDING,
|
|
@@ -26,6 +27,8 @@ const MenuContent = ({ onHide, values, preselectIndex, onNextMenu, onPreviousMen
|
|
|
26
27
|
const containerRef = (0, react_1.useRef)(null);
|
|
27
28
|
const isMobileLayout = (0, mobile_layout_1.useMobileLayout)();
|
|
28
29
|
const [subMenuActivated, setSubMenuActivated] = (0, react_1.useState)(false);
|
|
30
|
+
const typeaheadQueryRef = (0, react_1.useRef)('');
|
|
31
|
+
const typeaheadTimeoutRef = (0, react_1.useRef)(null);
|
|
29
32
|
if (values[0].type === 'divider') {
|
|
30
33
|
throw new Error('first value cant be divide');
|
|
31
34
|
}
|
|
@@ -38,6 +41,13 @@ const MenuContent = ({ onHide, values, preselectIndex, onNextMenu, onPreviousMen
|
|
|
38
41
|
const onItemSelected = (0, react_1.useCallback)((id) => {
|
|
39
42
|
setSelectedItem(id);
|
|
40
43
|
}, []);
|
|
44
|
+
const clearTypeahead = (0, react_1.useCallback)(() => {
|
|
45
|
+
typeaheadQueryRef.current = '';
|
|
46
|
+
if (typeaheadTimeoutRef.current !== null) {
|
|
47
|
+
window.clearTimeout(typeaheadTimeoutRef.current);
|
|
48
|
+
typeaheadTimeoutRef.current = null;
|
|
49
|
+
}
|
|
50
|
+
}, []);
|
|
41
51
|
const isItemSelectable = (0, react_1.useCallback)((v) => {
|
|
42
52
|
return v.type !== 'divider' && !v.disabled;
|
|
43
53
|
}, []);
|
|
@@ -114,6 +124,35 @@ const MenuContent = ({ onHide, values, preselectIndex, onNextMenu, onPreviousMen
|
|
|
114
124
|
}
|
|
115
125
|
setSubMenuActivated('without-mouse');
|
|
116
126
|
}, [onNextMenu, selectedItem, values]);
|
|
127
|
+
const onTypeahead = (0, react_1.useCallback)((event) => {
|
|
128
|
+
if (event.ctrlKey ||
|
|
129
|
+
event.metaKey ||
|
|
130
|
+
event.altKey ||
|
|
131
|
+
event.key.length !== 1 ||
|
|
132
|
+
event.key.trim().length === 0) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
const { activeElement } = document;
|
|
136
|
+
if (activeElement instanceof HTMLInputElement ||
|
|
137
|
+
activeElement instanceof HTMLTextAreaElement) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
typeaheadQueryRef.current = `${typeaheadQueryRef.current}${event.key}`;
|
|
141
|
+
const matchedId = (0, menu_typeahead_1.findTypeaheadMenuItem)({
|
|
142
|
+
query: typeaheadQueryRef.current,
|
|
143
|
+
values,
|
|
144
|
+
});
|
|
145
|
+
if (matchedId !== null) {
|
|
146
|
+
setSelectedItem(matchedId);
|
|
147
|
+
}
|
|
148
|
+
if (typeaheadTimeoutRef.current !== null) {
|
|
149
|
+
window.clearTimeout(typeaheadTimeoutRef.current);
|
|
150
|
+
}
|
|
151
|
+
typeaheadTimeoutRef.current = window.setTimeout(() => {
|
|
152
|
+
typeaheadQueryRef.current = '';
|
|
153
|
+
typeaheadTimeoutRef.current = null;
|
|
154
|
+
}, 700);
|
|
155
|
+
}, [values]);
|
|
117
156
|
const containerWithHeight = (0, react_1.useMemo)(() => {
|
|
118
157
|
const containerStyles = { ...container };
|
|
119
158
|
if (fixedHeight === null) {
|
|
@@ -127,6 +166,25 @@ const MenuContent = ({ onHide, values, preselectIndex, onNextMenu, onPreviousMen
|
|
|
127
166
|
}
|
|
128
167
|
return containerStyles;
|
|
129
168
|
}, [fixedHeight, isMobileLayout]);
|
|
169
|
+
(0, react_1.useEffect)(() => {
|
|
170
|
+
if (!keybindings.isHighestContext ||
|
|
171
|
+
!process.env.KEYBOARD_SHORTCUTS_ENABLED) {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
const onKeyDown = (event) => {
|
|
175
|
+
onTypeahead(event);
|
|
176
|
+
};
|
|
177
|
+
window.addEventListener('keydown', onKeyDown);
|
|
178
|
+
return () => {
|
|
179
|
+
window.removeEventListener('keydown', onKeyDown);
|
|
180
|
+
clearTypeahead();
|
|
181
|
+
};
|
|
182
|
+
}, [clearTypeahead, keybindings.isHighestContext, onTypeahead]);
|
|
183
|
+
(0, react_1.useEffect)(() => {
|
|
184
|
+
return () => {
|
|
185
|
+
clearTypeahead();
|
|
186
|
+
};
|
|
187
|
+
}, [clearTypeahead]);
|
|
130
188
|
(0, react_1.useEffect)(() => {
|
|
131
189
|
const escapeBinding = keybindings.registerKeybinding({
|
|
132
190
|
event: 'keydown',
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.findTypeaheadMenuItem = void 0;
|
|
4
|
+
const getLabelToMatch = (value) => {
|
|
5
|
+
if (value.type === 'divider' || value.disabled) {
|
|
6
|
+
return null;
|
|
7
|
+
}
|
|
8
|
+
if (typeof value.label === 'string') {
|
|
9
|
+
return value.label;
|
|
10
|
+
}
|
|
11
|
+
return null;
|
|
12
|
+
};
|
|
13
|
+
const findTypeaheadMenuItem = ({ query, values, }) => {
|
|
14
|
+
const normalizedQuery = query.trim().toLowerCase();
|
|
15
|
+
if (normalizedQuery.length === 0) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
const matched = values.find((value) => {
|
|
19
|
+
const label = getLabelToMatch(value);
|
|
20
|
+
return label ? label.toLowerCase().startsWith(normalizedQuery) : false;
|
|
21
|
+
});
|
|
22
|
+
if (!matched || matched.type === 'divider') {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
return matched.id;
|
|
26
|
+
};
|
|
27
|
+
exports.findTypeaheadMenuItem = findTypeaheadMenuItem;
|
|
@@ -5,9 +5,11 @@ const jsx_runtime_1 = require("react/jsx-runtime");
|
|
|
5
5
|
const player_1 = require("@remotion/player");
|
|
6
6
|
const react_1 = require("react");
|
|
7
7
|
const remotion_1 = require("remotion");
|
|
8
|
+
const ErrorLoader_1 = require("../error-overlay/remotion-overlay/ErrorLoader");
|
|
8
9
|
const checkerboard_background_1 = require("../helpers/checkerboard-background");
|
|
9
10
|
const colors_1 = require("../helpers/colors");
|
|
10
11
|
const checkerboard_1 = require("../state/checkerboard");
|
|
12
|
+
const is_menu_item_1 = require("./Menu/is-menu-item");
|
|
11
13
|
const RenderPreview_1 = require("./RenderPreview");
|
|
12
14
|
const Spinner_1 = require("./Spinner");
|
|
13
15
|
const StaticFilePreview_1 = require("./StaticFilePreview");
|
|
@@ -22,6 +24,14 @@ const label = {
|
|
|
22
24
|
fontSize: 14,
|
|
23
25
|
color: colors_1.LIGHT_TEXT,
|
|
24
26
|
};
|
|
27
|
+
const assetMetadataErrorContainer = {
|
|
28
|
+
marginLeft: 'auto',
|
|
29
|
+
marginRight: 'auto',
|
|
30
|
+
width: '100%',
|
|
31
|
+
position: 'absolute',
|
|
32
|
+
height: '100%',
|
|
33
|
+
overflowY: 'auto',
|
|
34
|
+
};
|
|
25
35
|
const getPreviewFileType = (fileName) => {
|
|
26
36
|
var _a;
|
|
27
37
|
if (!fileName) {
|
|
@@ -68,10 +78,13 @@ const containerStyle = (options) => {
|
|
|
68
78
|
backgroundPosition: (0, checkerboard_background_1.getCheckerboardBackgroundPos)(checkerboardSize) /* Must be half of one side of the square */,
|
|
69
79
|
};
|
|
70
80
|
};
|
|
71
|
-
const VideoPreview = ({ canvasSize, contentDimensions, canvasContent, assetMetadata }) => {
|
|
81
|
+
const VideoPreview = ({ canvasSize, contentDimensions, canvasContent, assetMetadata, onRetryAssetMetadata, }) => {
|
|
72
82
|
if (assetMetadata && assetMetadata.type === 'not-found') {
|
|
73
83
|
return (jsx_runtime_1.jsx("div", { style: centeredContainer, children: jsx_runtime_1.jsx("div", { style: label, children: "File does not exist" }) }));
|
|
74
84
|
}
|
|
85
|
+
if (assetMetadata && assetMetadata.type === 'metadata-error') {
|
|
86
|
+
return (jsx_runtime_1.jsx("div", { style: assetMetadataErrorContainer, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: jsx_runtime_1.jsx(ErrorLoader_1.ErrorLoader, { canHaveDismissButton: false, keyboardShortcuts: false, error: assetMetadata.error, onRetry: onRetryAssetMetadata !== null && onRetryAssetMetadata !== void 0 ? onRetryAssetMetadata : null, calculateMetadata: false }, assetMetadata.error.stack) }));
|
|
87
|
+
}
|
|
75
88
|
if (contentDimensions === null) {
|
|
76
89
|
return (jsx_runtime_1.jsx("div", { style: centeredContainer, children: jsx_runtime_1.jsx(Spinner_1.Spinner, { duration: 0.5, size: 24 }) }));
|
|
77
90
|
}
|
|
@@ -262,6 +262,7 @@ const RenderButton = ({ readOnlyStudio, }) => {
|
|
|
262
262
|
initialTransparent: null,
|
|
263
263
|
initialMuted: null,
|
|
264
264
|
initialMediaCacheSizeInBytes: defaults.mediaCacheSizeInBytes,
|
|
265
|
+
initialAllowHtmlInCanvas: defaults.allowHtmlInCanvas,
|
|
265
266
|
});
|
|
266
267
|
}, [video, setSelectedModal, getCurrentFrame, props, inFrame, outFrame]);
|
|
267
268
|
const onClick = (0, react_1.useCallback)(() => {
|
|
@@ -19,8 +19,9 @@ const padding = {
|
|
|
19
19
|
const title = {
|
|
20
20
|
fontSize: 14,
|
|
21
21
|
};
|
|
22
|
+
const DESCRIPTION_FONT_SIZE_PX = 14;
|
|
22
23
|
const description = {
|
|
23
|
-
fontSize:
|
|
24
|
+
fontSize: DESCRIPTION_FONT_SIZE_PX,
|
|
24
25
|
maxWidth: 400,
|
|
25
26
|
};
|
|
26
27
|
const link = {
|
|
@@ -56,7 +57,14 @@ const OptionExplainer = ({ option }) => {
|
|
|
56
57
|
jsx_runtime_1.jsxs("div", { children: [
|
|
57
58
|
jsx_runtime_1.jsx("strong", { style: title, children: option.name }), option.docLink ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
|
|
58
59
|
jsx_runtime_1.jsx(layout_1.Spacing, { x: 1 }), jsx_runtime_1.jsx("a", { style: link, href: option.docLink, target: "_blank", children: "Docs" })
|
|
59
|
-
] })) : null] }), jsx_runtime_1.
|
|
60
|
+
] })) : null] }), jsx_runtime_1.jsxs("div", { style: description, children: [
|
|
61
|
+
jsx_runtime_1.jsx("style", { children: `
|
|
62
|
+
.__remotion-option-explainer-description a,
|
|
63
|
+
.__remotion-option-explainer-description code {
|
|
64
|
+
font-size: ${DESCRIPTION_FONT_SIZE_PX}px;
|
|
65
|
+
}
|
|
66
|
+
` }), jsx_runtime_1.jsx("div", { className: "__remotion-option-explainer-description", children: option.description('ssr') })
|
|
67
|
+
] })
|
|
60
68
|
] }), jsx_runtime_1.jsx(layout_1.Spacing, { y: 0.5, block: true }), jsx_runtime_1.jsx(MenuDivider_1.MenuDivider, {}), jsx_runtime_1.jsx(layout_1.Spacing, { y: 0.5, block: true }), jsx_runtime_1.jsxs("div", { children: [
|
|
61
69
|
jsx_runtime_1.jsxs("div", { style: infoRow, children: [
|
|
62
70
|
jsx_runtime_1.jsx("div", { style: infoRowLabel, children: "CLI flag" }), jsx_runtime_1.jsx("div", { style: flexSpacer }), jsx_runtime_1.jsxs("code", { children: ["--", option.cliFlag] }), jsx_runtime_1.jsx("div", { style: copyWrapper, children: jsx_runtime_1.jsx(CliCopyButton_1.CliCopyButton, { valueToCopy: option.cliFlag }) })
|
|
@@ -80,7 +80,7 @@ const validateOutnameForStill = ({ outName, stillImageFormat, }) => {
|
|
|
80
80
|
// TODO: Shortcut: Shift + R
|
|
81
81
|
// TODO: Apply defaultCodec
|
|
82
82
|
// TODO: Apply defaultOutName
|
|
83
|
-
const WebRenderModal = ({ initialFrame, defaultProps, inFrameMark, outFrameMark, initialLogLevel, initialLicenseKey, initialStillImageFormat, initialDefaultOutName, initialScale, initialDelayRenderTimeout, initialMediaCacheSizeInBytes, initialContainer, initialVideoCodec, initialAudioCodec, initialAudioBitrate, initialVideoBitrate, initialHardwareAcceleration, initialKeyframeIntervalInSeconds, initialTransparent, initialMuted, }) => {
|
|
83
|
+
const WebRenderModal = ({ initialFrame, defaultProps, inFrameMark, outFrameMark, initialLogLevel, initialLicenseKey, initialStillImageFormat, initialDefaultOutName, initialScale, initialDelayRenderTimeout, initialMediaCacheSizeInBytes, initialContainer, initialVideoCodec, initialAudioCodec, initialAudioBitrate, initialVideoBitrate, initialHardwareAcceleration, initialKeyframeIntervalInSeconds, initialTransparent, initialMuted, initialAllowHtmlInCanvas, }) => {
|
|
84
84
|
var _a;
|
|
85
85
|
const context = (0, react_1.useContext)(ResolveCompositionBeforeModal_1.ResolvedCompositionContext);
|
|
86
86
|
const { setSelectedModal } = (0, react_1.useContext)(modals_1.ModalsContext);
|
|
@@ -124,6 +124,7 @@ const WebRenderModal = ({ initialFrame, defaultProps, inFrameMark, outFrameMark,
|
|
|
124
124
|
const [muted, setMuted] = (0, react_1.useState)(initialMuted !== null && initialMuted !== void 0 ? initialMuted : false);
|
|
125
125
|
const [scale, setScale] = (0, react_1.useState)(initialScale !== null && initialScale !== void 0 ? initialScale : 1);
|
|
126
126
|
const [licenseKey, setLicenseKey] = (0, react_1.useState)(initialLicenseKey);
|
|
127
|
+
const [allowHtmlInCanvas, setAllowHtmlInCanvas] = (0, react_1.useState)(initialAllowHtmlInCanvas !== null && initialAllowHtmlInCanvas !== void 0 ? initialAllowHtmlInCanvas : false);
|
|
127
128
|
const encodableAudioCodecs = (0, use_encodable_audio_codecs_1.useEncodableAudioCodecs)(container);
|
|
128
129
|
const encodableVideoCodecs = (0, use_encodable_video_codecs_1.useEncodableVideoCodecs)(container);
|
|
129
130
|
const effectiveAudioCodec = (0, react_1.useMemo)(() => {
|
|
@@ -336,6 +337,7 @@ const WebRenderModal = ({ initialFrame, defaultProps, inFrameMark, outFrameMark,
|
|
|
336
337
|
logLevel,
|
|
337
338
|
licenseKey,
|
|
338
339
|
scale,
|
|
340
|
+
allowHtmlInCanvas,
|
|
339
341
|
}, compositionRef);
|
|
340
342
|
}
|
|
341
343
|
else {
|
|
@@ -362,6 +364,7 @@ const WebRenderModal = ({ initialFrame, defaultProps, inFrameMark, outFrameMark,
|
|
|
362
364
|
logLevel,
|
|
363
365
|
licenseKey,
|
|
364
366
|
scale,
|
|
367
|
+
allowHtmlInCanvas,
|
|
365
368
|
}, compositionRef);
|
|
366
369
|
}
|
|
367
370
|
setSidebarCollapsedState({ left: null, right: 'expanded' });
|
|
@@ -402,6 +405,7 @@ const WebRenderModal = ({ initialFrame, defaultProps, inFrameMark, outFrameMark,
|
|
|
402
405
|
addClientStillJob,
|
|
403
406
|
addClientVideoJob,
|
|
404
407
|
scale,
|
|
408
|
+
allowHtmlInCanvas,
|
|
405
409
|
]);
|
|
406
410
|
return (jsx_runtime_1.jsxs("div", { style: render_modals_1.outerModalStyle, children: [
|
|
407
411
|
jsx_runtime_1.jsx(ModalHeader_1.ModalHeader, { title: `Render ${resolvedComposition.id}` }), jsx_runtime_1.jsxs("div", { style: render_modals_1.container, children: [
|
|
@@ -426,7 +430,7 @@ const WebRenderModal = ({ initialFrame, defaultProps, inFrameMark, outFrameMark,
|
|
|
426
430
|
canUpdate: false,
|
|
427
431
|
reason: 'render dialogue',
|
|
428
432
|
determined: false,
|
|
429
|
-
} })) : tab === 'picture' ? (jsx_runtime_1.jsx(WebRenderModalPicture_1.WebRenderModalPicture, { renderMode: renderMode, videoBitrate: videoBitrate, setVideoBitrate: setVideoBitrate, keyframeIntervalInSeconds: keyframeIntervalInSeconds, setKeyframeIntervalInSeconds: setKeyframeIntervalInSeconds, transparent: transparent, setTransparent: setTransparent, scale: scale, setScale: setScale, compositionWidth: resolvedComposition.width, compositionHeight: resolvedComposition.height })) : tab === 'audio' ? (jsx_runtime_1.jsx(WebRenderModalAudio_1.WebRenderModalAudio, { renderMode: renderMode, muted: muted, setMuted: setMuted, audioCodec: audioCodec, setAudioCodec: setAudioCodec, audioBitrate: audioBitrate, setAudioBitrate: setAudioBitrate, container: container, encodableCodecs: encodableAudioCodecs, effectiveAudioCodec: effectiveAudioCodec })) : tab === 'advanced' ? (jsx_runtime_1.jsx(WebRenderModalAdvanced_1.WebRenderModalAdvanced, { renderMode: renderMode, delayRenderTimeout: delayRenderTimeout, setDelayRenderTimeout: setDelayRenderTimeout, mediaCacheSizeInBytes: mediaCacheSizeInBytes, setMediaCacheSizeInBytes: setMediaCacheSizeInBytes, hardwareAcceleration: hardwareAcceleration, setHardwareAcceleration: setHardwareAcceleration })) : (jsx_runtime_1.jsx(WebRenderModalLicense_1.WebRenderModalLicense, { licenseKey: licenseKey, setLicenseKey: setLicenseKey, initialPublicLicenseKey: initialLicenseKey })) })
|
|
433
|
+
} })) : tab === 'picture' ? (jsx_runtime_1.jsx(WebRenderModalPicture_1.WebRenderModalPicture, { renderMode: renderMode, videoBitrate: videoBitrate, setVideoBitrate: setVideoBitrate, keyframeIntervalInSeconds: keyframeIntervalInSeconds, setKeyframeIntervalInSeconds: setKeyframeIntervalInSeconds, transparent: transparent, setTransparent: setTransparent, scale: scale, setScale: setScale, compositionWidth: resolvedComposition.width, compositionHeight: resolvedComposition.height })) : tab === 'audio' ? (jsx_runtime_1.jsx(WebRenderModalAudio_1.WebRenderModalAudio, { renderMode: renderMode, muted: muted, setMuted: setMuted, audioCodec: audioCodec, setAudioCodec: setAudioCodec, audioBitrate: audioBitrate, setAudioBitrate: setAudioBitrate, container: container, encodableCodecs: encodableAudioCodecs, effectiveAudioCodec: effectiveAudioCodec })) : tab === 'advanced' ? (jsx_runtime_1.jsx(WebRenderModalAdvanced_1.WebRenderModalAdvanced, { renderMode: renderMode, delayRenderTimeout: delayRenderTimeout, setDelayRenderTimeout: setDelayRenderTimeout, mediaCacheSizeInBytes: mediaCacheSizeInBytes, setMediaCacheSizeInBytes: setMediaCacheSizeInBytes, hardwareAcceleration: hardwareAcceleration, setHardwareAcceleration: setHardwareAcceleration, allowHtmlInCanvas: allowHtmlInCanvas, setAllowHtmlInCanvas: setAllowHtmlInCanvas })) : (jsx_runtime_1.jsx(WebRenderModalLicense_1.WebRenderModalLicense, { licenseKey: licenseKey, setLicenseKey: setLicenseKey, initialPublicLicenseKey: initialLicenseKey })) })
|
|
430
434
|
] })
|
|
431
435
|
] }));
|
|
432
436
|
};
|
|
@@ -8,6 +8,8 @@ type WebRenderModalAdvancedProps = {
|
|
|
8
8
|
readonly setMediaCacheSizeInBytes: React.Dispatch<React.SetStateAction<number | null>>;
|
|
9
9
|
readonly hardwareAcceleration: 'no-preference' | 'prefer-hardware' | 'prefer-software';
|
|
10
10
|
readonly setHardwareAcceleration: (value: 'no-preference' | 'prefer-hardware' | 'prefer-software') => void;
|
|
11
|
+
readonly allowHtmlInCanvas: boolean;
|
|
12
|
+
readonly setAllowHtmlInCanvas: React.Dispatch<React.SetStateAction<boolean>>;
|
|
11
13
|
};
|
|
12
14
|
export declare const WebRenderModalAdvanced: React.FC<WebRenderModalAdvancedProps>;
|
|
13
15
|
export {};
|
|
@@ -13,7 +13,7 @@ const OptionExplainerBubble_1 = require("./OptionExplainerBubble");
|
|
|
13
13
|
const tabContainer = {
|
|
14
14
|
flex: 1,
|
|
15
15
|
};
|
|
16
|
-
const WebRenderModalAdvanced = ({ renderMode, delayRenderTimeout, setDelayRenderTimeout, mediaCacheSizeInBytes, setMediaCacheSizeInBytes, hardwareAcceleration, setHardwareAcceleration, }) => {
|
|
16
|
+
const WebRenderModalAdvanced = ({ renderMode, delayRenderTimeout, setDelayRenderTimeout, mediaCacheSizeInBytes, setMediaCacheSizeInBytes, hardwareAcceleration, setHardwareAcceleration, allowHtmlInCanvas, setAllowHtmlInCanvas, }) => {
|
|
17
17
|
const toggleCustomMediaCacheSizeInBytes = (0, react_1.useCallback)(() => {
|
|
18
18
|
setMediaCacheSizeInBytes((previous) => {
|
|
19
19
|
if (previous === null) {
|
|
@@ -22,6 +22,9 @@ const WebRenderModalAdvanced = ({ renderMode, delayRenderTimeout, setDelayRender
|
|
|
22
22
|
return null;
|
|
23
23
|
});
|
|
24
24
|
}, [setMediaCacheSizeInBytes]);
|
|
25
|
+
const toggleAllowHtmlInCanvas = (0, react_1.useCallback)(() => {
|
|
26
|
+
setAllowHtmlInCanvas((prev) => !prev);
|
|
27
|
+
}, [setAllowHtmlInCanvas]);
|
|
25
28
|
const changeMediaCacheSizeInBytes = (0, react_1.useCallback)((cb) => {
|
|
26
29
|
setMediaCacheSizeInBytes((prev) => {
|
|
27
30
|
if (prev === null) {
|
|
@@ -77,6 +80,11 @@ const WebRenderModalAdvanced = ({ renderMode, delayRenderTimeout, setDelayRender
|
|
|
77
80
|
] }), jsx_runtime_1.jsx("div", { style: layout_2.rightRow, children: jsx_runtime_1.jsx(Checkbox_1.Checkbox, { checked: mediaCacheSizeInBytes !== null, onChange: toggleCustomMediaCacheSizeInBytes, name: "media-cache-size" }) })
|
|
78
81
|
] }), mediaCacheSizeInBytes === null ? null : (jsx_runtime_1.jsx(NumberSetting_1.NumberSetting, { name: "@remotion/media cache size", formatter: (w) => `${w} bytes`, min: 0, max: 10000000000, step: 10 * 1024 * 1024, value: mediaCacheSizeInBytes, onValueChanged: changeMediaCacheSizeInBytes })), renderMode === 'video' ? (jsx_runtime_1.jsxs("div", { style: layout_2.optionRow, children: [
|
|
79
82
|
jsx_runtime_1.jsx("div", { style: layout_2.label, children: "Hardware Acceleration" }), jsx_runtime_1.jsx("div", { style: layout_2.rightRow, children: jsx_runtime_1.jsx(ComboBox_1.Combobox, { values: hardwareAccelerationOptions, selectedId: hardwareAcceleration, title: "Hardware Acceleration" }) })
|
|
80
|
-
] })) : null
|
|
83
|
+
] })) : null, jsx_runtime_1.jsxs("div", { style: layout_2.optionRow, children: [
|
|
84
|
+
jsx_runtime_1.jsxs("div", { style: layout_2.label, children: ["Allow HTML-in-canvas ",
|
|
85
|
+
jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(OptionExplainerBubble_1.OptionExplainerBubble, { id: "allowHtmlInCanvasOption" })
|
|
86
|
+
] }), jsx_runtime_1.jsx("div", { style: layout_2.rightRow, children: jsx_runtime_1.jsx(Checkbox_1.Checkbox, { checked: allowHtmlInCanvas, onChange: toggleAllowHtmlInCanvas, name: "allow-html-in-canvas" }) })
|
|
87
|
+
] })
|
|
88
|
+
] }));
|
|
81
89
|
};
|
|
82
90
|
exports.WebRenderModalAdvanced = WebRenderModalAdvanced;
|
|
@@ -25,7 +25,7 @@ const ClientRenderQueueProcessor = () => {
|
|
|
25
25
|
if (!compositionRef) {
|
|
26
26
|
throw new Error(`Composition not found for job ${job.id}`);
|
|
27
27
|
}
|
|
28
|
-
const
|
|
28
|
+
const blob = await (await (0, web_renderer_1.renderStillOnWeb)({
|
|
29
29
|
composition: {
|
|
30
30
|
component: compositionRef.component,
|
|
31
31
|
width: compositionRef.width,
|
|
@@ -37,7 +37,6 @@ const ClientRenderQueueProcessor = () => {
|
|
|
37
37
|
id: job.compositionId,
|
|
38
38
|
},
|
|
39
39
|
frame: job.frame,
|
|
40
|
-
imageFormat: job.imageFormat,
|
|
41
40
|
inputProps: job.inputProps,
|
|
42
41
|
delayRenderTimeoutInMilliseconds: job.delayRenderTimeout,
|
|
43
42
|
mediaCacheSizeInBytes: job.mediaCacheSizeInBytes,
|
|
@@ -45,7 +44,8 @@ const ClientRenderQueueProcessor = () => {
|
|
|
45
44
|
licenseKey: (_b = job.licenseKey) !== null && _b !== void 0 ? _b : undefined,
|
|
46
45
|
scale: job.scale,
|
|
47
46
|
signal,
|
|
48
|
-
|
|
47
|
+
allowHtmlInCanvas: job.allowHtmlInCanvas,
|
|
48
|
+
})).blob({ format: job.imageFormat });
|
|
49
49
|
return {
|
|
50
50
|
getBlob: () => Promise.resolve(blob),
|
|
51
51
|
width: compositionRef.width,
|
|
@@ -97,6 +97,7 @@ const ClientRenderQueueProcessor = () => {
|
|
|
97
97
|
},
|
|
98
98
|
outputTarget: 'web-fs',
|
|
99
99
|
licenseKey: (_c = job.licenseKey) !== null && _c !== void 0 ? _c : undefined,
|
|
100
|
+
allowHtmlInCanvas: job.allowHtmlInCanvas,
|
|
100
101
|
});
|
|
101
102
|
return {
|
|
102
103
|
getBlob,
|
|
@@ -48,7 +48,7 @@ const TimelineListItem = ({ nestedDepth, sequence, isCompact }) => {
|
|
|
48
48
|
const { hidden, setHidden } = (0, react_1.useContext)(remotion_1.Internals.SequenceVisibilityToggleContext);
|
|
49
49
|
const { expandedTracks, toggleTrack } = (0, react_1.useContext)(ExpandedTracksProvider_1.ExpandedTracksContext);
|
|
50
50
|
const originalLocation = (0, use_resolved_stack_1.useResolvedStack)((_a = sequence.stack) !== null && _a !== void 0 ? _a : null);
|
|
51
|
-
const nodePath = (0, use_sequence_props_subscription_1.useSequencePropsSubscription)(sequence, originalLocation, visualModeActive);
|
|
51
|
+
const { nodePath, jsxInMapCallback } = (0, use_sequence_props_subscription_1.useSequencePropsSubscription)(sequence, originalLocation, visualModeActive);
|
|
52
52
|
const validatedLocation = (0, react_1.useMemo)(() => {
|
|
53
53
|
var _a;
|
|
54
54
|
if (!originalLocation ||
|
|
@@ -64,6 +64,34 @@ const TimelineListItem = ({ nestedDepth, sequence, isCompact }) => {
|
|
|
64
64
|
}, [originalLocation]);
|
|
65
65
|
const canDeleteFromSource = Boolean(nodePath && (validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source));
|
|
66
66
|
const deleteDisabled = (0, react_1.useMemo)(() => !previewConnected || !sequence.controls || !canDeleteFromSource, [previewConnected, sequence.controls, canDeleteFromSource]);
|
|
67
|
+
const duplicateDisabled = deleteDisabled;
|
|
68
|
+
const onDuplicateSequenceFromSource = (0, react_1.useCallback)(async () => {
|
|
69
|
+
if (!(validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source) || !nodePath) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
if (jsxInMapCallback) {
|
|
73
|
+
const message = 'This sequence is rendered inside a .map() callback. Duplicating inserts another copy in that callback (affecting each list item). Continue?';
|
|
74
|
+
// eslint-disable-next-line no-alert -- native confirm before applying duplicate codemod in .map callbacks
|
|
75
|
+
if (!window.confirm(message)) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
const result = await (0, call_api_1.callApi)('/api/duplicate-jsx-node', {
|
|
81
|
+
fileName: validatedLocation.source,
|
|
82
|
+
nodePath,
|
|
83
|
+
});
|
|
84
|
+
if (result.success) {
|
|
85
|
+
(0, NotificationCenter_1.showNotification)('Duplicated sequence in source file', 2000);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
(0, NotificationCenter_1.showNotification)(result.reason, 4000);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
(0, NotificationCenter_1.showNotification)(err.message, 4000);
|
|
93
|
+
}
|
|
94
|
+
}, [jsxInMapCallback, nodePath, validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source]);
|
|
67
95
|
const onDeleteSequenceFromSource = (0, react_1.useCallback)(async () => {
|
|
68
96
|
if (!(validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source) || !nodePath) {
|
|
69
97
|
return;
|
|
@@ -89,6 +117,23 @@ const TimelineListItem = ({ nestedDepth, sequence, isCompact }) => {
|
|
|
89
117
|
return [];
|
|
90
118
|
}
|
|
91
119
|
return [
|
|
120
|
+
{
|
|
121
|
+
type: 'item',
|
|
122
|
+
id: 'duplicate-sequence',
|
|
123
|
+
keyHint: null,
|
|
124
|
+
label: 'Duplicate',
|
|
125
|
+
leftItem: null,
|
|
126
|
+
disabled: duplicateDisabled,
|
|
127
|
+
onClick: () => {
|
|
128
|
+
if (duplicateDisabled) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
onDuplicateSequenceFromSource();
|
|
132
|
+
},
|
|
133
|
+
quickSwitcherLabel: null,
|
|
134
|
+
subMenu: null,
|
|
135
|
+
value: 'duplicate-sequence',
|
|
136
|
+
},
|
|
92
137
|
{
|
|
93
138
|
type: 'item',
|
|
94
139
|
id: 'delete-sequence',
|
|
@@ -107,7 +152,13 @@ const TimelineListItem = ({ nestedDepth, sequence, isCompact }) => {
|
|
|
107
152
|
value: 'delete-sequence',
|
|
108
153
|
},
|
|
109
154
|
];
|
|
110
|
-
}, [
|
|
155
|
+
}, [
|
|
156
|
+
deleteDisabled,
|
|
157
|
+
duplicateDisabled,
|
|
158
|
+
onDeleteSequenceFromSource,
|
|
159
|
+
onDuplicateSequenceFromSource,
|
|
160
|
+
visualModeEnvEnabled,
|
|
161
|
+
]);
|
|
111
162
|
const isExpanded = visualModeActive && ((_b = expandedTracks[sequence.id]) !== null && _b !== void 0 ? _b : false);
|
|
112
163
|
const onToggleExpand = (0, react_1.useCallback)(() => {
|
|
113
164
|
toggleTrack(sequence.id);
|
|
@@ -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
|
+
};
|