@remotion/studio 4.0.472 → 4.0.473

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.
Files changed (133) hide show
  1. package/dist/api/rename-static-file.d.ts +6 -0
  2. package/dist/api/rename-static-file.js +18 -0
  3. package/dist/components/AssetSelector.js +45 -4
  4. package/dist/components/AssetSelectorItem.js +153 -27
  5. package/dist/components/Canvas.js +60 -11
  6. package/dist/components/ConfirmationDialog-types.d.ts +8 -0
  7. package/dist/components/ConfirmationDialog-types.js +2 -0
  8. package/dist/components/ConfirmationDialog.d.ts +7 -0
  9. package/dist/components/ConfirmationDialog.js +103 -0
  10. package/dist/components/ContextMenu.d.ts +9 -1
  11. package/dist/components/ContextMenu.js +49 -5
  12. package/dist/components/CurrentAsset.d.ts +1 -0
  13. package/dist/components/CurrentAsset.js +13 -2
  14. package/dist/components/EditorContent.js +15 -2
  15. package/dist/components/EditorContexts.js +2 -1
  16. package/dist/components/EditorRuler/Ruler.js +2 -0
  17. package/dist/components/ExplorerPanel.d.ts +0 -4
  18. package/dist/components/ExplorerPanel.js +8 -4
  19. package/dist/components/ExplorerPanelRef.d.ts +4 -0
  20. package/dist/components/ExplorerPanelRef.js +5 -0
  21. package/dist/components/FilePreview.d.ts +1 -1
  22. package/dist/components/InitialCompositionLoader.d.ts +0 -1
  23. package/dist/components/InitialCompositionLoader.js +5 -27
  24. package/dist/components/Menu/MenuItem.js +7 -1
  25. package/dist/components/Menu/SubMenu.js +5 -1
  26. package/dist/components/Menu/portals.js +17 -8
  27. package/dist/components/MenuToolbar.js +5 -1
  28. package/dist/components/ModalContainer.js +6 -1
  29. package/dist/components/Modals.js +6 -2
  30. package/dist/components/NewComposition/ComboBox.js +8 -2
  31. package/dist/components/NewComposition/DeleteStaticFile.d.ts +4 -0
  32. package/dist/components/NewComposition/DeleteStaticFile.js +44 -0
  33. package/dist/components/NewComposition/RenameStaticFile.d.ts +4 -0
  34. package/dist/components/NewComposition/RenameStaticFile.js +118 -0
  35. package/dist/components/OptionsPanel.js +5 -1
  36. package/dist/components/OutlineToggle.d.ts +2 -0
  37. package/dist/components/OutlineToggle.js +20 -0
  38. package/dist/components/Preview.d.ts +0 -2
  39. package/dist/components/Preview.js +23 -33
  40. package/dist/components/PreviewToolbar.js +19 -6
  41. package/dist/components/RenderButton.js +8 -2
  42. package/dist/components/RenderPreview.js +2 -2
  43. package/dist/components/SelectedOutlineOverlay.d.ts +24 -0
  44. package/dist/components/SelectedOutlineOverlay.js +190 -22
  45. package/dist/components/ShowOutlinesProvider.d.ts +4 -0
  46. package/dist/components/ShowOutlinesProvider.js +24 -0
  47. package/dist/components/SizeSelector.js +3 -3
  48. package/dist/components/Splitter/SplitterHandle.js +2 -0
  49. package/dist/components/StaticFilePreview.js +2 -2
  50. package/dist/components/Timeline/KeyframeSettingsModal.d.ts +15 -0
  51. package/dist/components/Timeline/KeyframeSettingsModal.js +150 -0
  52. package/dist/components/Timeline/Timeline.js +3 -13
  53. package/dist/components/Timeline/TimelineClipboardKeybindings.d.ts +25 -2
  54. package/dist/components/Timeline/TimelineClipboardKeybindings.js +234 -20
  55. package/dist/components/Timeline/TimelineDeleteKeybindings.js +12 -2
  56. package/dist/components/Timeline/TimelineEffectItem.js +1 -0
  57. package/dist/components/Timeline/TimelineEffectPropItem.js +52 -2
  58. package/dist/components/Timeline/TimelineKeyframeControls.js +5 -15
  59. package/dist/components/Timeline/TimelineKeyframeDiamond.js +24 -21
  60. package/dist/components/Timeline/TimelineKeyframeDiamondIcon.d.ts +6 -0
  61. package/dist/components/Timeline/TimelineKeyframeDiamondIcon.js +14 -0
  62. package/dist/components/Timeline/TimelineKeyframeDragState.d.ts +17 -0
  63. package/dist/components/Timeline/TimelineKeyframeDragState.js +39 -0
  64. package/dist/components/Timeline/TimelineList.js +2 -2
  65. package/dist/components/Timeline/TimelineMediaInfo.d.ts +0 -13
  66. package/dist/components/Timeline/TimelineMediaInfo.js +8 -73
  67. package/dist/components/Timeline/TimelineScaleField.js +1 -1
  68. package/dist/components/Timeline/TimelineSequenceItem.d.ts +1 -0
  69. package/dist/components/Timeline/TimelineSequenceItem.js +276 -22
  70. package/dist/components/Timeline/TimelineSequencePropItem.js +81 -16
  71. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +25 -28
  72. package/dist/components/Timeline/apply-effect-response-to-code-values.d.ts +5 -0
  73. package/dist/components/Timeline/apply-effect-response-to-code-values.js +19 -0
  74. package/dist/components/Timeline/call-add-keyframe.js +2 -0
  75. package/dist/components/Timeline/call-move-keyframe.d.ts +19 -0
  76. package/dist/components/Timeline/call-move-keyframe.js +71 -0
  77. package/dist/components/Timeline/call-update-keyframe-settings.d.ts +22 -0
  78. package/dist/components/Timeline/call-update-keyframe-settings.js +52 -0
  79. package/dist/components/Timeline/delete-selected-timeline-item.d.ts +7 -4
  80. package/dist/components/Timeline/delete-selected-timeline-item.js +33 -21
  81. package/dist/components/Timeline/duplicate-selected-timeline-item.d.ts +4 -2
  82. package/dist/components/Timeline/duplicate-selected-timeline-item.js +39 -34
  83. package/dist/components/Timeline/get-bounded-keyframe-drag-delta.d.ts +8 -0
  84. package/dist/components/Timeline/get-bounded-keyframe-drag-delta.js +12 -0
  85. package/dist/components/Timeline/get-keyframe-navigation.d.ts +2 -2
  86. package/dist/components/Timeline/get-keyframe-navigation.js +14 -6
  87. package/dist/components/Timeline/reset-selected-timeline-props.js +3 -2
  88. package/dist/components/Timeline/save-effect-prop.d.ts +14 -3
  89. package/dist/components/Timeline/save-effect-prop.js +36 -18
  90. package/dist/components/Timeline/save-prop-queue.d.ts +2 -1
  91. package/dist/components/Timeline/save-prop-queue.js +5 -2
  92. package/dist/components/Timeline/save-sequence-prop.d.ts +2 -7
  93. package/dist/components/Timeline/save-sequence-prop.js +33 -30
  94. package/dist/components/Timeline/should-clear-selection-on-pointer-down.d.ts +3 -0
  95. package/dist/components/Timeline/should-clear-selection-on-pointer-down.js +7 -0
  96. package/dist/components/Timeline/timeline-asset-link.d.ts +13 -0
  97. package/dist/components/Timeline/timeline-asset-link.js +37 -0
  98. package/dist/components/Timeline/timeline-translate-utils.js +4 -1
  99. package/dist/components/Timeline/use-timeline-keyframe-drag.d.ts +10 -0
  100. package/dist/components/Timeline/use-timeline-keyframe-drag.js +378 -0
  101. package/dist/components/import-assets.d.ts +16 -0
  102. package/dist/components/import-assets.js +155 -18
  103. package/dist/components/load-canvas-content-from-url.d.ts +1 -0
  104. package/dist/components/load-canvas-content-from-url.js +9 -3
  105. package/dist/components/use-select-asset.d.ts +1 -0
  106. package/dist/components/use-select-asset.js +30 -0
  107. package/dist/error-overlay/error-origin.d.ts +3 -0
  108. package/dist/error-overlay/error-origin.js +42 -0
  109. package/dist/error-overlay/react-overlay/listen-to-runtime-errors.js +6 -2
  110. package/dist/error-overlay/remotion-overlay/ErrorLoader.js +38 -0
  111. package/dist/error-overlay/remotion-overlay/ShortcutHint.js +1 -1
  112. package/dist/error-overlay/remotion-overlay/log-studio-error.d.ts +3 -0
  113. package/dist/error-overlay/remotion-overlay/log-studio-error.js +27 -0
  114. package/dist/esm/{chunk-48grt472.js → chunk-q0jkt0zq.js} +21961 -19299
  115. package/dist/esm/internals.mjs +21961 -19299
  116. package/dist/esm/previewEntry.mjs +20600 -17914
  117. package/dist/esm/renderEntry.mjs +1 -1
  118. package/dist/helpers/get-asset-metadata.js +2 -2
  119. package/dist/helpers/get-preview-file-type.d.ts +2 -0
  120. package/dist/helpers/get-preview-file-type.js +33 -0
  121. package/dist/helpers/install-required-package.d.ts +1 -0
  122. package/dist/helpers/install-required-package.js +39 -0
  123. package/dist/helpers/remote-asset-drag.d.ts +4 -0
  124. package/dist/helpers/remote-asset-drag.js +73 -0
  125. package/dist/helpers/use-asset-drag-events.d.ts +5 -2
  126. package/dist/helpers/use-asset-drag-events.js +13 -2
  127. package/dist/hot-middleware-client/client.js +6 -0
  128. package/dist/state/editor-outlines.d.ts +8 -0
  129. package/dist/state/editor-outlines.js +18 -0
  130. package/dist/state/modals.d.ts +19 -2
  131. package/package.json +10 -10
  132. package/dist/helpers/detect-file-type.d.ts +0 -69
  133. package/dist/helpers/detect-file-type.js +0 -278
@@ -0,0 +1,6 @@
1
+ import type { RenameStaticFileResponse } from '@remotion/studio-shared';
2
+ export declare const renameStaticFile: ({ oldRelativePath, newRelativePath, }: {
3
+ oldRelativePath: string;
4
+ newRelativePath: string;
5
+ }) => Promise<RenameStaticFileResponse>;
6
+ export { RenameStaticFileResponse };
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.renameStaticFile = void 0;
4
+ const remotion_1 = require("remotion");
5
+ const call_api_1 = require("../components/call-api");
6
+ const renameStaticFile = ({ oldRelativePath, newRelativePath, }) => {
7
+ if (!(0, remotion_1.getRemotionEnvironment)().isStudio) {
8
+ throw new Error('renameStaticFile() is only available in the Studio');
9
+ }
10
+ if (window.remotion_isReadOnlyStudio) {
11
+ throw new Error('renameStaticFile() is not available in Read-Only Studio');
12
+ }
13
+ return (0, call_api_1.callApi)('/api/rename-static-file', {
14
+ oldRelativePath,
15
+ newRelativePath,
16
+ });
17
+ };
18
+ exports.renameStaticFile = renameStaticFile;
@@ -1,7 +1,37 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
5
35
  Object.defineProperty(exports, "__esModule", { value: true });
6
36
  exports.AssetSelector = void 0;
7
37
  const jsx_runtime_1 = require("react/jsx-runtime");
@@ -13,7 +43,7 @@ const colors_1 = require("../helpers/colors");
13
43
  const create_folder_tree_1 = require("../helpers/create-folder-tree");
14
44
  const persist_boolean_map_1 = require("../helpers/persist-boolean-map");
15
45
  const persist_open_folders_1 = require("../helpers/persist-open-folders");
16
- const use_asset_drag_events_1 = __importDefault(require("../helpers/use-asset-drag-events"));
46
+ const use_asset_drag_events_1 = __importStar(require("../helpers/use-asset-drag-events"));
17
47
  const folders_1 = require("../state/folders");
18
48
  const z_index_1 = require("../state/z-index");
19
49
  const AssetSelectorItem_1 = require("./AssetSelectorItem");
@@ -82,13 +112,24 @@ const AssetSelector = ({ readOnlyStudio }) => {
82
112
  setDropLocation,
83
113
  });
84
114
  const onDragOver = (0, react_1.useCallback)((e) => {
115
+ if (!(0, use_asset_drag_events_1.isFileDragEvent)(e)) {
116
+ return;
117
+ }
85
118
  e.preventDefault();
86
119
  }, []);
87
120
  const onDrop = (0, react_1.useCallback)(async (e) => {
88
121
  try {
122
+ if (!(0, use_asset_drag_events_1.isFileDragEvent)(e)) {
123
+ setDropLocation(null);
124
+ return;
125
+ }
89
126
  e.preventDefault();
90
127
  e.stopPropagation();
91
128
  const { files } = e.dataTransfer;
129
+ if (files.length === 0) {
130
+ setDropLocation(null);
131
+ return;
132
+ }
92
133
  const assetPath = dropLocation !== null && dropLocation !== void 0 ? dropLocation : null;
93
134
  const makePath = (file) => {
94
135
  return [assetPath, file.name].filter(Boolean).join('/');
@@ -32,25 +32,27 @@ var __importStar = (this && this.__importStar) || (function () {
32
32
  return result;
33
33
  };
34
34
  })();
35
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
37
- };
38
35
  Object.defineProperty(exports, "__esModule", { value: true });
39
36
  exports.AssetFolderTree = void 0;
40
37
  const jsx_runtime_1 = require("react/jsx-runtime");
41
- const react_1 = __importStar(require("react"));
38
+ const studio_shared_1 = require("@remotion/studio-shared");
39
+ const react_1 = require("react");
42
40
  const remotion_1 = require("remotion");
43
41
  const no_react_1 = require("remotion/no-react");
42
+ const client_id_1 = require("../helpers/client-id");
44
43
  const colors_1 = require("../helpers/colors");
45
44
  const copy_text_1 = require("../helpers/copy-text");
46
45
  const mobile_layout_1 = require("../helpers/mobile-layout");
47
46
  const sidebar_scroll_into_view_1 = require("../helpers/sidebar-scroll-into-view");
48
47
  const url_state_1 = require("../helpers/url-state");
49
- const use_asset_drag_events_1 = __importDefault(require("../helpers/use-asset-drag-events"));
48
+ const use_asset_drag_events_1 = __importStar(require("../helpers/use-asset-drag-events"));
50
49
  const clipboard_1 = require("../icons/clipboard");
51
50
  const file_1 = require("../icons/file");
52
51
  const folder_1 = require("../icons/folder");
52
+ const modals_1 = require("../state/modals");
53
53
  const sidebar_1 = require("../state/sidebar");
54
+ const ContextMenu_1 = require("./ContextMenu");
55
+ const import_assets_1 = require("./import-assets");
54
56
  const InlineAction_1 = require("./InlineAction");
55
57
  const layout_1 = require("./layout");
56
58
  const NotificationCenter_1 = require("./Notifications/NotificationCenter");
@@ -128,13 +130,19 @@ const AssetFolderItem = ({ tabIndex, item, level, parentFolder, toggleFolder, dr
128
130
  return (jsx_runtime_1.jsxs("div", { onDragEnter: onDragEnter, onDragLeave: onDragLeave, style: {
129
131
  backgroundColor: isDropDiv ? colors_1.CLEAR_HOVER : colors_1.BACKGROUND,
130
132
  }, children: [
131
- jsx_runtime_1.jsx("div", { style: folderStyle, onPointerEnter: onPointerEnter, onPointerLeave: onPointerLeave, tabIndex: tabIndex, title: item.name, onClick: onClick, onDragEnter: () => {
133
+ jsx_runtime_1.jsx("div", { style: folderStyle, onPointerEnter: onPointerEnter, onPointerLeave: onPointerLeave, tabIndex: tabIndex, title: item.name, onClick: onClick, onDragEnter: (event) => {
134
+ if (!(0, use_asset_drag_events_1.isFileDragEvent)(event)) {
135
+ return;
136
+ }
132
137
  if (!item.expanded) {
133
138
  openFolderTimerRef.current = window.setTimeout(() => {
134
139
  toggleFolder(item.name, parentFolder);
135
140
  }, 1000);
136
141
  }
137
- }, onDragLeave: () => {
142
+ }, onDragLeave: (event) => {
143
+ if (!(0, use_asset_drag_events_1.isFileDragEvent)(event)) {
144
+ return;
145
+ }
138
146
  if (openFolderTimerRef.current) {
139
147
  clearTimeout(openFolderTimerRef.current);
140
148
  }
@@ -156,7 +164,11 @@ exports.AssetFolderTree = AssetFolderTree;
156
164
  const AssetSelectorItem = ({ item, tabIndex, level, parentFolder, readOnlyStudio }) => {
157
165
  const isMobileLayout = (0, mobile_layout_1.useMobileLayout)();
158
166
  const [hovered, setHovered] = (0, react_1.useState)(false);
167
+ const [isDragging, setIsDragging] = (0, react_1.useState)(false);
159
168
  const { setSidebarCollapsedState } = (0, react_1.useContext)(sidebar_1.SidebarContext);
169
+ const { setSelectedModal } = (0, react_1.useContext)(modals_1.ModalsContext);
170
+ const connectionStatus = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx)
171
+ .previewServerState.type;
160
172
  const onPointerEnter = (0, react_1.useCallback)(() => {
161
173
  setHovered(true);
162
174
  }, []);
@@ -171,6 +183,9 @@ const AssetSelectorItem = ({ item, tabIndex, level, parentFolder, readOnlyStudio
171
183
  }
172
184
  return false;
173
185
  }, [canvasContent, relativePath]);
186
+ const canDragAsset = (0, react_1.useMemo)(() => {
187
+ return !readOnlyStudio && (0, import_assets_1.getAssetElementFromPath)(relativePath) !== null;
188
+ }, [readOnlyStudio, relativePath]);
174
189
  const onPointerLeave = (0, react_1.useCallback)(() => {
175
190
  setHovered(false);
176
191
  }, []);
@@ -195,6 +210,18 @@ const AssetSelectorItem = ({ item, tabIndex, level, parentFolder, readOnlyStudio
195
210
  setCanvasContent,
196
211
  setSidebarCollapsedState,
197
212
  ]);
213
+ const onDragStart = (0, react_1.useCallback)((e) => {
214
+ if (!canDragAsset) {
215
+ e.preventDefault();
216
+ return;
217
+ }
218
+ setIsDragging(true);
219
+ e.dataTransfer.effectAllowed = 'copy';
220
+ e.dataTransfer.setData(studio_shared_1.ASSET_DRAG_MIME_TYPE, JSON.stringify((0, studio_shared_1.makeAssetDragData)(relativePath)));
221
+ }, [canDragAsset, relativePath]);
222
+ const onDragEnd = (0, react_1.useCallback)(() => {
223
+ setIsDragging(false);
224
+ }, []);
198
225
  const style = (0, react_1.useMemo)(() => {
199
226
  return {
200
227
  ...itemStyle,
@@ -221,21 +248,17 @@ const AssetSelectorItem = ({ item, tabIndex, level, parentFolder, readOnlyStudio
221
248
  const renderCopyAction = (0, react_1.useCallback)((color) => {
222
249
  return jsx_runtime_1.jsx(clipboard_1.ClipboardIcon, { style: revealIconStyle, color: color });
223
250
  }, []);
224
- const revealInExplorer = react_1.default.useCallback((e) => {
225
- e.stopPropagation();
226
- (0, actions_1.openInFileExplorer)({
227
- directory: window.remotion_publicFolderExists +
228
- '/' +
229
- parentFolder +
230
- '/' +
231
- item.name,
232
- }).catch((err) => {
233
- (0, NotificationCenter_1.showNotification)(`Could not open file: ${err.message}`, 2000);
251
+ const copyFileName = (0, react_1.useCallback)(() => {
252
+ (0, copy_text_1.copyText)(item.name)
253
+ .then(() => {
254
+ (0, NotificationCenter_1.showNotification)(`Copied '${item.name}' to clipboard`, 1000);
255
+ })
256
+ .catch((err) => {
257
+ (0, NotificationCenter_1.showNotification)(`Could not copy: ${err.message}`, 2000);
234
258
  });
235
- }, [item.name, parentFolder]);
236
- const copyToClipboard = (0, react_1.useCallback)((e) => {
237
- e.stopPropagation();
238
- const content = `staticFile("${[parentFolder, item.name].join('/')}")`;
259
+ }, [item.name]);
260
+ const copyStaticFilePath = (0, react_1.useCallback)(() => {
261
+ const content = `staticFile("${relativePath}")`;
239
262
  (0, copy_text_1.copyText)(content)
240
263
  .then(() => {
241
264
  (0, NotificationCenter_1.showNotification)(`Copied '${content}' to clipboard`, 1000);
@@ -243,10 +266,113 @@ const AssetSelectorItem = ({ item, tabIndex, level, parentFolder, readOnlyStudio
243
266
  .catch((err) => {
244
267
  (0, NotificationCenter_1.showNotification)(`Could not copy: ${err.message}`, 2000);
245
268
  });
246
- }, [item.name, parentFolder]);
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: [
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: [
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: [
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 })
251
- ] }))] })) : null] }) }));
269
+ }, [relativePath]);
270
+ const openAssetInExplorer = (0, react_1.useCallback)(() => {
271
+ if (!window.remotion_publicFolderExists) {
272
+ (0, NotificationCenter_1.showNotification)('Could not find the public folder', 2000);
273
+ return;
274
+ }
275
+ (0, actions_1.openInFileExplorer)({
276
+ directory: window.remotion_publicFolderExists + '/' + relativePath,
277
+ }).catch((err) => {
278
+ (0, NotificationCenter_1.showNotification)(`Could not open file: ${err.message}`, 2000);
279
+ });
280
+ }, [relativePath]);
281
+ const serverActionDisabled = readOnlyStudio || connectionStatus !== 'connected';
282
+ const contextMenu = (0, react_1.useMemo)(() => {
283
+ return [
284
+ {
285
+ id: 'copy-asset-file-name',
286
+ keyHint: null,
287
+ label: 'Copy file name',
288
+ leftItem: null,
289
+ onClick: copyFileName,
290
+ quickSwitcherLabel: 'Copy asset file name',
291
+ subMenu: null,
292
+ type: 'item',
293
+ value: 'copy-asset-file-name',
294
+ },
295
+ {
296
+ id: 'copy-asset-static-file-path',
297
+ keyHint: null,
298
+ label: 'Copy staticFile() path',
299
+ leftItem: null,
300
+ onClick: copyStaticFilePath,
301
+ quickSwitcherLabel: 'Copy staticFile() path',
302
+ subMenu: null,
303
+ type: 'item',
304
+ value: 'copy-asset-static-file-path',
305
+ },
306
+ {
307
+ type: 'divider',
308
+ id: 'asset-file-actions-divider',
309
+ },
310
+ {
311
+ id: 'open-asset-in-explorer',
312
+ keyHint: null,
313
+ label: 'Open in Explorer',
314
+ leftItem: null,
315
+ onClick: openAssetInExplorer,
316
+ quickSwitcherLabel: 'Open asset in Explorer',
317
+ subMenu: null,
318
+ type: 'item',
319
+ value: 'open-asset-in-explorer',
320
+ disabled: serverActionDisabled || window.remotion_publicFolderExists === null,
321
+ },
322
+ {
323
+ id: 'rename-asset',
324
+ keyHint: null,
325
+ label: 'Rename...',
326
+ leftItem: null,
327
+ onClick: () => {
328
+ setSelectedModal({
329
+ type: 'rename-static-file',
330
+ relativePath,
331
+ });
332
+ },
333
+ quickSwitcherLabel: 'Rename asset...',
334
+ subMenu: null,
335
+ type: 'item',
336
+ value: 'rename-asset',
337
+ disabled: serverActionDisabled,
338
+ },
339
+ {
340
+ id: 'delete-asset',
341
+ keyHint: null,
342
+ label: 'Delete...',
343
+ leftItem: null,
344
+ onClick: () => {
345
+ setSelectedModal({
346
+ type: 'delete-static-file',
347
+ relativePath,
348
+ });
349
+ },
350
+ quickSwitcherLabel: 'Delete asset...',
351
+ subMenu: null,
352
+ type: 'item',
353
+ value: 'delete-asset',
354
+ disabled: serverActionDisabled,
355
+ },
356
+ ];
357
+ }, [
358
+ copyFileName,
359
+ copyStaticFilePath,
360
+ openAssetInExplorer,
361
+ relativePath,
362
+ serverActionDisabled,
363
+ setSelectedModal,
364
+ ]);
365
+ const revealInExplorer = (0, react_1.useCallback)((e) => {
366
+ e.stopPropagation();
367
+ openAssetInExplorer();
368
+ }, [openAssetInExplorer]);
369
+ const copyToClipboard = (0, react_1.useCallback)((e) => {
370
+ e.stopPropagation();
371
+ copyStaticFilePath();
372
+ }, [copyStaticFilePath]);
373
+ return (jsx_runtime_1.jsx(ContextMenu_1.ContextMenu, { values: contextMenu, onOpen: null, children: 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, draggable: canDragAsset, onDragStart: onDragStart, onDragEnd: onDragEnd, tabIndex: tabIndex, title: item.name, children: [
374
+ 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 && !isDragging ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
375
+ jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(InlineAction_1.InlineAction, { title: "Copy staticFile() path", renderAction: renderCopyAction, onClick: copyToClipboard }), serverActionDisabled ? null : (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
376
+ 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 })
377
+ ] }))] })) : null] }) }) }));
252
378
  };
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.Canvas = void 0;
7
7
  const jsx_runtime_1 = require("react/jsx-runtime");
8
+ const studio_shared_1 = require("@remotion/studio-shared");
8
9
  const react_1 = require("react");
9
10
  const remotion_1 = require("remotion");
10
11
  const client_id_1 = require("../helpers/client-id");
@@ -12,6 +13,7 @@ const colors_1 = require("../helpers/colors");
12
13
  const get_asset_metadata_1 = require("../helpers/get-asset-metadata");
13
14
  const get_effective_translation_1 = require("../helpers/get-effective-translation");
14
15
  const open_in_editor_1 = require("../helpers/open-in-editor");
16
+ const remote_asset_drag_1 = require("../helpers/remote-asset-drag");
15
17
  const smooth_zoom_1 = require("../helpers/smooth-zoom");
16
18
  const use_keybinding_1 = require("../helpers/use-keybinding");
17
19
  const canvas_ref_1 = require("../state/canvas-ref");
@@ -44,6 +46,25 @@ const isFileDragEvent = (event) => {
44
46
  var _b;
45
47
  return Array.from((_b = (_a = event.dataTransfer) === null || _a === void 0 ? void 0 : _a.types) !== null && _b !== void 0 ? _b : []).includes('Files');
46
48
  };
49
+ const isAssetDragEvent = (event) => {
50
+ var _a;
51
+ var _b;
52
+ return Array.from((_b = (_a = event.dataTransfer) === null || _a === void 0 ? void 0 : _a.types) !== null && _b !== void 0 ? _b : []).includes(studio_shared_1.ASSET_DRAG_MIME_TYPE);
53
+ };
54
+ const isRemoteAssetDragEvent = (event) => {
55
+ return (!isFileDragEvent(event) &&
56
+ !isAssetDragEvent(event) &&
57
+ (0, remote_asset_drag_1.hasRemoteAssetDragData)(event.dataTransfer));
58
+ };
59
+ const getAssetDragPath = (event) => {
60
+ var _a, _b;
61
+ var _c;
62
+ const value = (_a = event.dataTransfer) === null || _a === void 0 ? void 0 : _a.getData(studio_shared_1.ASSET_DRAG_MIME_TYPE);
63
+ if (!value) {
64
+ return null;
65
+ }
66
+ return (_c = (_b = (0, studio_shared_1.parseAssetDragData)(value)) === null || _b === void 0 ? void 0 : _b.assetPath) !== null && _c !== void 0 ? _c : null;
67
+ };
47
68
  const isDragEventInsideCanvas = (event) => {
48
69
  const { current } = canvas_ref_1.canvasRef;
49
70
  if (!current) {
@@ -467,7 +488,9 @@ const Canvas = ({ canvasContent, size }) => {
467
488
  }, [fetchMetadata]);
468
489
  const onDragOver = (0, react_1.useCallback)((event) => {
469
490
  if (!canDropAssets ||
470
- !isFileDragEvent(event) ||
491
+ (!isFileDragEvent(event) &&
492
+ !isAssetDragEvent(event) &&
493
+ !isRemoteAssetDragEvent(event)) ||
471
494
  !isDragEventInsideCanvas(event)) {
472
495
  return;
473
496
  }
@@ -482,23 +505,49 @@ const Canvas = ({ canvasContent, size }) => {
482
505
  if (!canDropAssets ||
483
506
  compositionFile === null ||
484
507
  currentCompositionId === null ||
485
- !isFileDragEvent(event) ||
508
+ (!isFileDragEvent(event) &&
509
+ !isAssetDragEvent(event) &&
510
+ !isRemoteAssetDragEvent(event)) ||
486
511
  !isDragEventInsideCanvas(event)) {
487
512
  return;
488
513
  }
489
514
  event.preventDefault();
490
515
  event.stopPropagation();
491
- const files = Array.from((_b = (_a = event.dataTransfer) === null || _a === void 0 ? void 0 : _a.files) !== null && _b !== void 0 ? _b : []);
492
- if (files.length === 0) {
493
- return;
494
- }
495
516
  setIsAddingAsset(true);
496
517
  try {
497
- await (0, import_assets_1.importAssets)({
498
- files,
499
- compositionFile,
500
- compositionId: currentCompositionId,
501
- });
518
+ if (isFileDragEvent(event)) {
519
+ const files = Array.from((_b = (_a = event.dataTransfer) === null || _a === void 0 ? void 0 : _a.files) !== null && _b !== void 0 ? _b : []);
520
+ if (files.length === 0) {
521
+ return;
522
+ }
523
+ await (0, import_assets_1.importAssets)({
524
+ files,
525
+ compositionFile,
526
+ compositionId: currentCompositionId,
527
+ });
528
+ }
529
+ else if (isAssetDragEvent(event)) {
530
+ const assetPath = getAssetDragPath(event);
531
+ if (assetPath === null) {
532
+ return;
533
+ }
534
+ await (0, import_assets_1.insertExistingAssets)({
535
+ assetPaths: [assetPath],
536
+ compositionFile,
537
+ compositionId: currentCompositionId,
538
+ });
539
+ }
540
+ else {
541
+ const url = (0, remote_asset_drag_1.getRemoteAssetUrlFromDataTransfer)(event.dataTransfer);
542
+ if (url === null) {
543
+ return;
544
+ }
545
+ await (0, import_assets_1.importRemoteAsset)({
546
+ url,
547
+ compositionFile,
548
+ compositionId: currentCompositionId,
549
+ });
550
+ }
502
551
  }
503
552
  finally {
504
553
  setIsAddingAsset(false);
@@ -0,0 +1,8 @@
1
+ import type React from 'react';
2
+ export type ConfirmationDialogOptions = {
3
+ readonly title: string;
4
+ readonly message: React.ReactNode;
5
+ readonly confirmLabel?: string;
6
+ readonly cancelLabel?: string;
7
+ };
8
+ export type ConfirmationDialogFunction = (options: ConfirmationDialogOptions) => Promise<boolean>;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import type { ConfirmationDialogState } from '../state/modals';
3
+ import type { ConfirmationDialogFunction } from './ConfirmationDialog-types';
4
+ export declare const useConfirmationDialog: () => ConfirmationDialogFunction;
5
+ export declare const ConfirmationDialog: React.FC<{
6
+ readonly state: ConfirmationDialogState;
7
+ }>;
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ConfirmationDialog = exports.useConfirmationDialog = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const ShortcutHint_1 = require("../error-overlay/remotion-overlay/ShortcutHint");
7
+ const modals_1 = require("../state/modals");
8
+ const Button_1 = require("./Button");
9
+ const layout_1 = require("./layout");
10
+ const ModalButton_1 = require("./ModalButton");
11
+ const ModalContainer_1 = require("./ModalContainer");
12
+ const ModalFooter_1 = require("./ModalFooter");
13
+ const ModalHeader_1 = require("./ModalHeader");
14
+ const content = {
15
+ padding: 16,
16
+ fontSize: 14,
17
+ flex: 1,
18
+ minWidth: 420,
19
+ maxWidth: 560,
20
+ lineHeight: 1.4,
21
+ };
22
+ const useConfirmationDialog = () => {
23
+ const { setSelectedModal } = (0, react_1.useContext)(modals_1.ModalsContext);
24
+ return (0, react_1.useCallback)((options) => {
25
+ return new Promise((resolve) => {
26
+ var _a, _b;
27
+ let settled = false;
28
+ const settle = (result) => {
29
+ if (settled) {
30
+ return;
31
+ }
32
+ settled = true;
33
+ resolve(result);
34
+ };
35
+ setSelectedModal({
36
+ type: 'confirmation-dialog',
37
+ id: String(Math.random()),
38
+ title: options.title,
39
+ message: options.message,
40
+ confirmLabel: (_a = options.confirmLabel) !== null && _a !== void 0 ? _a : 'Continue',
41
+ cancelLabel: (_b = options.cancelLabel) !== null && _b !== void 0 ? _b : 'Cancel',
42
+ onConfirm: () => settle(true),
43
+ onCancel: () => settle(false),
44
+ });
45
+ });
46
+ }, [setSelectedModal]);
47
+ };
48
+ exports.useConfirmationDialog = useConfirmationDialog;
49
+ const ConfirmationDialog = ({ state }) => {
50
+ const { setSelectedModal } = (0, react_1.useContext)(modals_1.ModalsContext);
51
+ const settledRef = (0, react_1.useRef)(false);
52
+ const closeCurrentModal = (0, react_1.useCallback)(() => {
53
+ setSelectedModal((modal) => (modal === null || modal === void 0 ? void 0 : modal.type) === 'confirmation-dialog' && modal.id === state.id
54
+ ? null
55
+ : modal);
56
+ }, [setSelectedModal, state.id]);
57
+ const settle = (0, react_1.useCallback)((confirmed) => {
58
+ if (settledRef.current) {
59
+ return;
60
+ }
61
+ settledRef.current = true;
62
+ closeCurrentModal();
63
+ if (confirmed) {
64
+ state.onConfirm();
65
+ }
66
+ else {
67
+ state.onCancel();
68
+ }
69
+ }, [closeCurrentModal, state]);
70
+ (0, react_1.useEffect)(() => {
71
+ return () => {
72
+ if (settledRef.current) {
73
+ return;
74
+ }
75
+ settledRef.current = true;
76
+ state.onCancel();
77
+ };
78
+ }, [state]);
79
+ const onCancel = (0, react_1.useCallback)(() => {
80
+ settle(false);
81
+ }, [settle]);
82
+ const onConfirm = (0, react_1.useCallback)(() => {
83
+ settle(true);
84
+ }, [settle]);
85
+ const onSubmit = (0, react_1.useCallback)((e) => {
86
+ e.preventDefault();
87
+ onConfirm();
88
+ }, [onConfirm]);
89
+ const cancelStyle = (0, react_1.useMemo)(() => {
90
+ return {
91
+ minWidth: 90,
92
+ };
93
+ }, []);
94
+ return (jsx_runtime_1.jsxs(ModalContainer_1.ModalContainer, { onOutsideClick: onCancel, onEscape: onCancel, children: [
95
+ jsx_runtime_1.jsx(ModalHeader_1.ModalHeader, { title: state.title, onClose: onCancel }), jsx_runtime_1.jsxs("form", { onSubmit: onSubmit, children: [
96
+ jsx_runtime_1.jsx("div", { style: content, children: state.message }), jsx_runtime_1.jsx(ModalFooter_1.ModalFooterContainer, { children: jsx_runtime_1.jsxs(layout_1.Row, { align: "center", children: [
97
+ jsx_runtime_1.jsx(layout_1.Flex, {}), jsx_runtime_1.jsx(Button_1.Button, { onClick: onCancel, style: cancelStyle, children: state.cancelLabel }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 1 }), jsx_runtime_1.jsxs(ModalButton_1.ModalButton, { onClick: onConfirm, autoFocus: true, children: [state.confirmLabel, jsx_runtime_1.jsx(ShortcutHint_1.ShortcutHint, { keyToPress: "\u21B5", cmdOrCtrl: false })
98
+ ] })
99
+ ] }) })
100
+ ] })
101
+ ] }));
102
+ };
103
+ exports.ConfirmationDialog = ConfirmationDialog;
@@ -1,12 +1,20 @@
1
1
  import React from 'react';
2
2
  import type { ComboboxValue } from './NewComposition/ComboBox';
3
+ type ContextMenuOpenHandler = () => false | void;
4
+ type ContextMenuTargetOpenResult = false | void | readonly ComboboxValue[];
5
+ type ContextMenuTargetOpenHandler = (event: MouseEvent) => ContextMenuTargetOpenResult | Promise<ContextMenuTargetOpenResult>;
3
6
  type ContextMenuProps = {
4
7
  readonly children: React.ReactNode;
5
8
  readonly values: ComboboxValue[];
6
- readonly onOpen: (() => void) | null;
9
+ readonly onOpen: ContextMenuOpenHandler | null;
7
10
  readonly style?: React.CSSProperties;
8
11
  readonly className?: string;
9
12
  readonly onPointerDown?: React.PointerEventHandler<HTMLDivElement>;
10
13
  };
11
14
  export declare const ContextMenu: React.ForwardRefExoticComponent<ContextMenuProps & React.RefAttributes<HTMLDivElement>>;
15
+ export declare const ContextMenuForTarget: React.FC<{
16
+ readonly triggerRef: React.RefObject<HTMLElement | SVGElement | null>;
17
+ readonly values: ComboboxValue[];
18
+ readonly onOpen: ContextMenuTargetOpenHandler | null;
19
+ }>;
12
20
  export {};