@remotion/studio 4.0.472 → 4.0.474

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 (165) 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 +177 -27
  5. package/dist/components/Canvas.js +131 -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 +5 -2
  30. package/dist/components/NewComposition/ComboBox.js +8 -2
  31. package/dist/components/NewComposition/InputDragger.d.ts +1 -0
  32. package/dist/components/NewComposition/InputDragger.js +9 -6
  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 +29 -3
  44. package/dist/components/SelectedOutlineOverlay.js +259 -80
  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/SequencePropsObserver.js +3 -3
  53. package/dist/components/Timeline/Timeline.js +3 -13
  54. package/dist/components/Timeline/TimelineClipboardKeybindings.d.ts +26 -3
  55. package/dist/components/Timeline/TimelineClipboardKeybindings.js +242 -25
  56. package/dist/components/Timeline/TimelineDeleteKeybindings.js +23 -11
  57. package/dist/components/Timeline/TimelineEffectItem.js +8 -7
  58. package/dist/components/Timeline/TimelineEffectPropItem.js +69 -19
  59. package/dist/components/Timeline/TimelineExpandedKeyframeRow.js +6 -1
  60. package/dist/components/Timeline/TimelineExpandedSection.js +5 -5
  61. package/dist/components/Timeline/TimelineKeyframeControls.js +13 -23
  62. package/dist/components/Timeline/TimelineKeyframeDiamond.js +24 -22
  63. package/dist/components/Timeline/TimelineKeyframeDiamondIcon.d.ts +6 -0
  64. package/dist/components/Timeline/TimelineKeyframeDiamondIcon.js +14 -0
  65. package/dist/components/Timeline/TimelineKeyframeDragState.d.ts +17 -0
  66. package/dist/components/Timeline/TimelineKeyframeDragState.js +39 -0
  67. package/dist/components/Timeline/TimelineKeyframeEasingLine.d.ts +9 -0
  68. package/dist/components/Timeline/TimelineKeyframeEasingLine.js +120 -0
  69. package/dist/components/Timeline/TimelineKeyframedValue.js +1 -1
  70. package/dist/components/Timeline/TimelineList.js +2 -2
  71. package/dist/components/Timeline/TimelineMediaInfo.d.ts +0 -13
  72. package/dist/components/Timeline/TimelineMediaInfo.js +8 -73
  73. package/dist/components/Timeline/TimelineNumberField.js +15 -7
  74. package/dist/components/Timeline/TimelineRotationField.js +17 -11
  75. package/dist/components/Timeline/TimelineScaleField.js +17 -13
  76. package/dist/components/Timeline/TimelineSelection.d.ts +15 -0
  77. package/dist/components/Timeline/TimelineSelection.js +26 -1
  78. package/dist/components/Timeline/TimelineSequence.js +6 -6
  79. package/dist/components/Timeline/TimelineSequenceItem.d.ts +1 -0
  80. package/dist/components/Timeline/TimelineSequenceItem.js +297 -36
  81. package/dist/components/Timeline/TimelineSequencePropItem.js +113 -48
  82. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.d.ts +5 -5
  83. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +69 -70
  84. package/dist/components/Timeline/TimelineTranslateField.js +24 -19
  85. package/dist/components/Timeline/TimelineUvCoordinateField.js +18 -12
  86. package/dist/components/Timeline/apply-effect-response-to-prop-statuses.d.ts +5 -0
  87. package/dist/components/Timeline/apply-effect-response-to-prop-statuses.js +19 -0
  88. package/dist/components/Timeline/call-add-keyframe.d.ts +5 -5
  89. package/dist/components/Timeline/call-add-keyframe.js +6 -4
  90. package/dist/components/Timeline/call-delete-keyframe.d.ts +7 -7
  91. package/dist/components/Timeline/call-delete-keyframe.js +7 -7
  92. package/dist/components/Timeline/call-move-keyframe.d.ts +19 -0
  93. package/dist/components/Timeline/call-move-keyframe.js +71 -0
  94. package/dist/components/Timeline/call-update-keyframe-settings.d.ts +22 -0
  95. package/dist/components/Timeline/call-update-keyframe-settings.js +52 -0
  96. package/dist/components/Timeline/delete-selected-keyframe.d.ts +5 -5
  97. package/dist/components/Timeline/delete-selected-keyframe.js +5 -5
  98. package/dist/components/Timeline/delete-selected-timeline-item.d.ts +10 -7
  99. package/dist/components/Timeline/delete-selected-timeline-item.js +37 -23
  100. package/dist/components/Timeline/duplicate-selected-timeline-item.d.ts +4 -2
  101. package/dist/components/Timeline/duplicate-selected-timeline-item.js +39 -34
  102. package/dist/components/Timeline/get-bounded-keyframe-drag-delta.d.ts +8 -0
  103. package/dist/components/Timeline/get-bounded-keyframe-drag-delta.js +12 -0
  104. package/dist/components/Timeline/get-keyframe-navigation.d.ts +2 -2
  105. package/dist/components/Timeline/get-keyframe-navigation.js +14 -6
  106. package/dist/components/Timeline/get-node-keyframes.d.ts +3 -3
  107. package/dist/components/Timeline/get-node-keyframes.js +4 -4
  108. package/dist/components/Timeline/get-timeline-easing-segments.d.ts +9 -0
  109. package/dist/components/Timeline/get-timeline-easing-segments.js +19 -0
  110. package/dist/components/Timeline/reset-selected-timeline-props.d.ts +7 -7
  111. package/dist/components/Timeline/reset-selected-timeline-props.js +13 -12
  112. package/dist/components/Timeline/save-effect-prop.d.ts +16 -5
  113. package/dist/components/Timeline/save-effect-prop.js +37 -19
  114. package/dist/components/Timeline/save-prop-queue.d.ts +4 -3
  115. package/dist/components/Timeline/save-prop-queue.js +6 -3
  116. package/dist/components/Timeline/save-sequence-prop.d.ts +5 -10
  117. package/dist/components/Timeline/save-sequence-prop.js +35 -32
  118. package/dist/components/Timeline/should-clear-selection-on-pointer-down.d.ts +3 -0
  119. package/dist/components/Timeline/should-clear-selection-on-pointer-down.js +7 -0
  120. package/dist/components/Timeline/timeline-asset-link.d.ts +13 -0
  121. package/dist/components/Timeline/timeline-asset-link.js +37 -0
  122. package/dist/components/Timeline/timeline-field-utils.d.ts +10 -0
  123. package/dist/components/Timeline/timeline-field-utils.js +26 -5
  124. package/dist/components/Timeline/timeline-translate-utils.d.ts +1 -1
  125. package/dist/components/Timeline/timeline-translate-utils.js +6 -4
  126. package/dist/components/Timeline/use-expanded-track-keyframe-rows.js +7 -7
  127. package/dist/components/Timeline/use-sequence-props-subscription.js +3 -3
  128. package/dist/components/Timeline/use-timeline-height.js +3 -3
  129. package/dist/components/Timeline/use-timeline-keyframe-drag.d.ts +10 -0
  130. package/dist/components/Timeline/use-timeline-keyframe-drag.js +380 -0
  131. package/dist/components/import-assets.d.ts +31 -0
  132. package/dist/components/import-assets.js +216 -17
  133. package/dist/components/load-canvas-content-from-url.d.ts +1 -0
  134. package/dist/components/load-canvas-content-from-url.js +9 -3
  135. package/dist/components/use-select-asset.d.ts +1 -0
  136. package/dist/components/use-select-asset.js +30 -0
  137. package/dist/error-overlay/error-origin.d.ts +3 -0
  138. package/dist/error-overlay/error-origin.js +42 -0
  139. package/dist/error-overlay/react-overlay/listen-to-runtime-errors.js +6 -2
  140. package/dist/error-overlay/remotion-overlay/ErrorLoader.js +38 -0
  141. package/dist/error-overlay/remotion-overlay/ShortcutHint.js +1 -1
  142. package/dist/error-overlay/remotion-overlay/log-studio-error.d.ts +3 -0
  143. package/dist/error-overlay/remotion-overlay/log-studio-error.js +27 -0
  144. package/dist/esm/{chunk-48grt472.js → chunk-xjvc8qen.js} +21838 -18862
  145. package/dist/esm/internals.mjs +21838 -18862
  146. package/dist/esm/previewEntry.mjs +21127 -18127
  147. package/dist/esm/renderEntry.mjs +1 -1
  148. package/dist/helpers/get-asset-metadata.js +2 -2
  149. package/dist/helpers/get-preview-file-type.d.ts +2 -0
  150. package/dist/helpers/get-preview-file-type.js +33 -0
  151. package/dist/helpers/install-required-package.d.ts +1 -0
  152. package/dist/helpers/install-required-package.js +39 -0
  153. package/dist/helpers/remote-asset-drag.d.ts +4 -0
  154. package/dist/helpers/remote-asset-drag.js +73 -0
  155. package/dist/helpers/timeline-layout.d.ts +6 -6
  156. package/dist/helpers/timeline-layout.js +5 -5
  157. package/dist/helpers/use-asset-drag-events.d.ts +5 -2
  158. package/dist/helpers/use-asset-drag-events.js +13 -2
  159. package/dist/hot-middleware-client/client.js +6 -0
  160. package/dist/state/editor-outlines.d.ts +8 -0
  161. package/dist/state/editor-outlines.js +18 -0
  162. package/dist/state/modals.d.ts +16 -2
  163. package/package.json +10 -10
  164. package/dist/helpers/detect-file-type.d.ts +0 -69
  165. package/dist/helpers/detect-file-type.js +0 -278
@@ -1,9 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.importAssets = exports.pickFilesToImport = void 0;
3
+ exports.insertComponent = exports.insertExistingAssets = exports.insertRemoteAudio = exports.importRemoteAsset = exports.importAssets = exports.pickFilesToImport = exports.getAssetElementFromPath = exports.getAssetElement = void 0;
4
+ const studio_shared_1 = require("@remotion/studio-shared");
4
5
  const get_static_files_1 = require("../api/get-static-files");
5
6
  const write_static_file_1 = require("../api/write-static-file");
6
- const detect_file_type_1 = require("../helpers/detect-file-type");
7
+ const install_required_package_1 = require("../helpers/install-required-package");
7
8
  const call_api_1 = require("./call-api");
8
9
  const NotificationCenter_1 = require("./Notifications/NotificationCenter");
9
10
  const getAssetElement = ({ fileType, src, }) => {
@@ -15,6 +16,7 @@ const getAssetElement = ({ fileType, src, }) => {
15
16
  type: 'asset',
16
17
  assetType: 'image',
17
18
  src,
19
+ srcType: 'static',
18
20
  dimensions: fileType.dimensions,
19
21
  };
20
22
  }
@@ -23,6 +25,7 @@ const getAssetElement = ({ fileType, src, }) => {
23
25
  type: 'asset',
24
26
  assetType: 'gif',
25
27
  src,
28
+ srcType: 'static',
26
29
  dimensions: fileType.dimensions,
27
30
  };
28
31
  }
@@ -34,11 +37,73 @@ const getAssetElement = ({ fileType, src, }) => {
34
37
  type: 'asset',
35
38
  assetType: 'video',
36
39
  src,
40
+ srcType: 'static',
41
+ dimensions: null,
42
+ };
43
+ }
44
+ if (fileType.type === 'wav' ||
45
+ fileType.type === 'mp3' ||
46
+ fileType.type === 'aac' ||
47
+ fileType.type === 'flac') {
48
+ return {
49
+ type: 'asset',
50
+ assetType: 'audio',
51
+ src,
52
+ srcType: 'static',
53
+ dimensions: null,
54
+ };
55
+ }
56
+ return null;
57
+ };
58
+ exports.getAssetElement = getAssetElement;
59
+ const getAssetElementFromPath = (assetPath) => {
60
+ var _a;
61
+ if (!assetPath || assetPath.includes('\\')) {
62
+ return null;
63
+ }
64
+ const extension = (_a = assetPath.split('.').pop()) === null || _a === void 0 ? void 0 : _a.toLowerCase();
65
+ if (!extension || extension === assetPath.toLowerCase()) {
66
+ return null;
67
+ }
68
+ if (['png', 'jpg', 'jpeg', 'webp', 'bmp'].includes(extension)) {
69
+ return {
70
+ type: 'asset',
71
+ assetType: 'image',
72
+ src: assetPath,
73
+ srcType: 'static',
74
+ dimensions: null,
75
+ };
76
+ }
77
+ if (extension === 'gif') {
78
+ return {
79
+ type: 'asset',
80
+ assetType: 'gif',
81
+ src: assetPath,
82
+ srcType: 'static',
83
+ dimensions: null,
84
+ };
85
+ }
86
+ if (['mp4', 'm4v', 'mov', 'avi', 'webm', 'ts', 'm2ts'].includes(extension)) {
87
+ return {
88
+ type: 'asset',
89
+ assetType: 'video',
90
+ src: assetPath,
91
+ srcType: 'static',
92
+ dimensions: null,
93
+ };
94
+ }
95
+ if (['wav', 'mp3', 'aac', 'flac'].includes(extension)) {
96
+ return {
97
+ type: 'asset',
98
+ assetType: 'audio',
99
+ src: assetPath,
100
+ srcType: 'static',
37
101
  dimensions: null,
38
102
  };
39
103
  }
40
104
  return null;
41
105
  };
106
+ exports.getAssetElementFromPath = getAssetElementFromPath;
42
107
  const getAssetLabel = (element) => {
43
108
  if (element.type !== 'asset') {
44
109
  throw new Error('Expected asset element');
@@ -49,7 +114,16 @@ const getAssetLabel = (element) => {
49
114
  if (element.assetType === 'video') {
50
115
  return '<Video>';
51
116
  }
52
- return '<Gif>';
117
+ if (element.assetType === 'gif') {
118
+ return '<Gif>';
119
+ }
120
+ if (element.assetType === 'audio') {
121
+ return '<Audio>';
122
+ }
123
+ throw new Error('Unsupported asset type');
124
+ };
125
+ const getComponentLabel = (component) => {
126
+ return `<${component.componentName}>`;
53
127
  };
54
128
  const pickFilesToImport = () => {
55
129
  return new Promise((resolve) => {
@@ -80,6 +154,39 @@ const pickFilesToImport = () => {
80
154
  });
81
155
  };
82
156
  exports.pickFilesToImport = pickFilesToImport;
157
+ const notifyInsertedAssets = (insertedLabels) => {
158
+ if (insertedLabels.length === 1) {
159
+ (0, NotificationCenter_1.showNotification)(`Added ${insertedLabels[0]} to source file`, 2000);
160
+ }
161
+ else if (insertedLabels.length > 1) {
162
+ (0, NotificationCenter_1.showNotification)(`Added ${insertedLabels.length} assets to source file`, 2000);
163
+ }
164
+ };
165
+ const notifyUnsupportedFiles = (unsupportedFiles) => {
166
+ if (unsupportedFiles.length === 1) {
167
+ (0, NotificationCenter_1.showNotification)(`Cannot add ${unsupportedFiles[0]}: Unsupported file type`, 3000);
168
+ }
169
+ else if (unsupportedFiles.length > 1) {
170
+ (0, NotificationCenter_1.showNotification)(`Skipped ${unsupportedFiles.length} unsupported files`, 3000);
171
+ }
172
+ };
173
+ const insertAssetElement = async ({ compositionFile, compositionId, element, }) => {
174
+ const requiredPackage = (0, studio_shared_1.getRequiredPackageForInsertableElement)(element);
175
+ await (0, install_required_package_1.installRequiredPackages)(requiredPackage ? [requiredPackage] : []);
176
+ const result = await (0, call_api_1.callApi)('/api/insert-jsx-element', {
177
+ compositionFile,
178
+ compositionId,
179
+ element,
180
+ });
181
+ if (!result.success) {
182
+ (0, NotificationCenter_1.showNotification)(result.reason, 4000);
183
+ return false;
184
+ }
185
+ return true;
186
+ };
187
+ const downloadRemoteAsset = async (url) => {
188
+ return (0, call_api_1.callApi)('/api/download-remote-asset', { url });
189
+ };
83
190
  const importAssets = async ({ compositionFile, compositionId, files, }) => {
84
191
  if (files.length === 0) {
85
192
  return;
@@ -107,8 +214,8 @@ const importAssets = async ({ compositionFile, compositionId, files, }) => {
107
214
  try {
108
215
  for (const file of files) {
109
216
  const contents = await file.arrayBuffer();
110
- const fileType = (0, detect_file_type_1.detectFileType)(new Uint8Array(contents));
111
- const element = getAssetElement({
217
+ const fileType = (0, studio_shared_1.detectFileType)(new Uint8Array(contents));
218
+ const element = (0, exports.getAssetElement)({
112
219
  fileType,
113
220
  src: file.name,
114
221
  });
@@ -124,34 +231,126 @@ const importAssets = async ({ compositionFile, compositionId, files, }) => {
124
231
  });
125
232
  addedStaticFiles.push(file.name);
126
233
  }
127
- const result = await (0, call_api_1.callApi)('/api/insert-jsx-element', {
234
+ const inserted = await insertAssetElement({
128
235
  compositionFile,
129
236
  compositionId,
130
237
  element,
131
238
  });
132
- if (!result.success) {
239
+ if (!inserted) {
133
240
  notifyAddedStaticFiles();
134
- (0, NotificationCenter_1.showNotification)(result.reason, 4000);
135
241
  return;
136
242
  }
137
243
  insertedLabels.push(getAssetLabel(element));
138
244
  }
139
245
  notifyAddedStaticFiles();
140
- if (insertedLabels.length === 1) {
141
- (0, NotificationCenter_1.showNotification)(`Added ${insertedLabels[0]} to source file`, 2000);
246
+ notifyInsertedAssets(insertedLabels);
247
+ notifyUnsupportedFiles(unsupportedFiles);
248
+ }
249
+ catch (error) {
250
+ (0, NotificationCenter_1.showNotification)(`Could not add asset: ${error instanceof Error ? error.message : String(error)}`, 4000);
251
+ }
252
+ };
253
+ exports.importAssets = importAssets;
254
+ const importRemoteAsset = async ({ compositionFile, compositionId, url, }) => {
255
+ try {
256
+ const { assetPath, created, element } = await downloadRemoteAsset(url);
257
+ if (created) {
258
+ (0, NotificationCenter_1.showNotification)(`Created ${assetPath} in public folder`, 3000);
142
259
  }
143
- else if (insertedLabels.length > 1) {
144
- (0, NotificationCenter_1.showNotification)(`Added ${insertedLabels.length} assets to source file`, 2000);
260
+ const inserted = await insertAssetElement({
261
+ compositionFile,
262
+ compositionId,
263
+ element,
264
+ });
265
+ if (!inserted) {
266
+ return;
145
267
  }
146
- if (unsupportedFiles.length === 1) {
147
- (0, NotificationCenter_1.showNotification)(`Cannot add ${unsupportedFiles[0]}: Unsupported file type`, 3000);
268
+ notifyInsertedAssets([getAssetLabel(element)]);
269
+ }
270
+ catch (error) {
271
+ (0, NotificationCenter_1.showNotification)(`Could not add remote asset: ${error instanceof Error ? error.message : String(error)}`, 4000);
272
+ }
273
+ };
274
+ exports.importRemoteAsset = importRemoteAsset;
275
+ const insertRemoteAudio = async ({ compositionFile, compositionId, url, }) => {
276
+ if (!(0, studio_shared_1.isUrl)(url)) {
277
+ (0, NotificationCenter_1.showNotification)('Cannot add sound effect: Unsupported URL', 3000);
278
+ return;
279
+ }
280
+ const element = {
281
+ type: 'asset',
282
+ assetType: 'audio',
283
+ src: url,
284
+ srcType: 'remote',
285
+ dimensions: null,
286
+ };
287
+ try {
288
+ const inserted = await insertAssetElement({
289
+ compositionFile,
290
+ compositionId,
291
+ element,
292
+ });
293
+ if (!inserted) {
294
+ return;
148
295
  }
149
- else if (unsupportedFiles.length > 1) {
150
- (0, NotificationCenter_1.showNotification)(`Skipped ${unsupportedFiles.length} unsupported files`, 3000);
296
+ notifyInsertedAssets([getAssetLabel(element)]);
297
+ }
298
+ catch (error) {
299
+ (0, NotificationCenter_1.showNotification)(`Could not add sound effect: ${error instanceof Error ? error.message : String(error)}`, 4000);
300
+ }
301
+ };
302
+ exports.insertRemoteAudio = insertRemoteAudio;
303
+ const insertExistingAssets = async ({ assetPaths, compositionFile, compositionId, }) => {
304
+ if (assetPaths.length === 0) {
305
+ return;
306
+ }
307
+ const insertedLabels = [];
308
+ const unsupportedFiles = [];
309
+ try {
310
+ for (const assetPath of assetPaths) {
311
+ const element = (0, exports.getAssetElementFromPath)(assetPath);
312
+ if (element === null) {
313
+ unsupportedFiles.push(assetPath);
314
+ continue;
315
+ }
316
+ const inserted = await insertAssetElement({
317
+ compositionFile,
318
+ compositionId,
319
+ element,
320
+ });
321
+ if (!inserted) {
322
+ return;
323
+ }
324
+ insertedLabels.push(getAssetLabel(element));
151
325
  }
326
+ notifyInsertedAssets(insertedLabels);
327
+ notifyUnsupportedFiles(unsupportedFiles);
152
328
  }
153
329
  catch (error) {
154
330
  (0, NotificationCenter_1.showNotification)(`Could not add asset: ${error instanceof Error ? error.message : String(error)}`, 4000);
155
331
  }
156
332
  };
157
- exports.importAssets = importAssets;
333
+ exports.insertExistingAssets = insertExistingAssets;
334
+ const insertComponent = async ({ component, compositionFile, compositionId, }) => {
335
+ try {
336
+ const inserted = await insertAssetElement({
337
+ compositionFile,
338
+ compositionId,
339
+ element: {
340
+ type: 'component',
341
+ componentName: component.componentName,
342
+ importName: component.importName,
343
+ importPath: component.importPath,
344
+ props: component.props,
345
+ },
346
+ });
347
+ if (!inserted) {
348
+ return;
349
+ }
350
+ (0, NotificationCenter_1.showNotification)(`Added ${getComponentLabel(component)} to source file`, 2000);
351
+ }
352
+ catch (error) {
353
+ (0, NotificationCenter_1.showNotification)(`Could not add component: ${error instanceof Error ? error.message : String(error)}`, 4000);
354
+ }
355
+ };
356
+ exports.insertComponent = insertComponent;
@@ -1,2 +1,3 @@
1
1
  import type { CanvasContent } from 'remotion';
2
+ export declare const deriveCanvasContentFromRoute: (route: string) => CanvasContent | null;
2
3
  export declare const deriveCanvasContentFromUrl: () => CanvasContent | null;
@@ -1,13 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.deriveCanvasContentFromUrl = void 0;
3
+ exports.deriveCanvasContentFromUrl = exports.deriveCanvasContentFromRoute = void 0;
4
4
  const url_state_1 = require("../helpers/url-state");
5
- const deriveCanvasContentFromUrl = () => {
6
- const route = (0, url_state_1.getRoute)();
5
+ const deriveCanvasContentFromRoute = (route) => {
7
6
  const substrings = route.split('/').filter(Boolean);
8
7
  // CJK-named composition IDs are not automatically reselected after page refresh
9
8
  const lastPart = substrings[substrings.length - 1];
10
9
  if (substrings[0] === 'assets') {
10
+ if (!lastPart || substrings.length === 1) {
11
+ return null;
12
+ }
11
13
  return {
12
14
  type: 'asset',
13
15
  asset: decodeURIComponent(route.substring('/assets/'.length)),
@@ -27,4 +29,8 @@ const deriveCanvasContentFromUrl = () => {
27
29
  }
28
30
  return null;
29
31
  };
32
+ exports.deriveCanvasContentFromRoute = deriveCanvasContentFromRoute;
33
+ const deriveCanvasContentFromUrl = () => {
34
+ return (0, exports.deriveCanvasContentFromRoute)((0, url_state_1.getRoute)());
35
+ };
30
36
  exports.deriveCanvasContentFromUrl = deriveCanvasContentFromUrl;
@@ -0,0 +1 @@
1
+ export declare const useSelectAsset: () => (asset: string) => void;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useSelectAsset = void 0;
4
+ const react_1 = require("react");
5
+ const remotion_1 = require("remotion");
6
+ const folders_1 = require("../state/folders");
7
+ const ExplorerPanelRef_1 = require("./ExplorerPanelRef");
8
+ const useSelectAsset = () => {
9
+ const { setCanvasContent } = (0, react_1.useContext)(remotion_1.Internals.CompositionSetters);
10
+ const { setAssetFoldersExpanded } = (0, react_1.useContext)(folders_1.FolderContext);
11
+ return (0, react_1.useCallback)((asset) => {
12
+ var _a;
13
+ setCanvasContent({ type: 'asset', asset });
14
+ (_a = ExplorerPanelRef_1.explorerSidebarTabs.current) === null || _a === void 0 ? void 0 : _a.selectAssetsPanel();
15
+ setAssetFoldersExpanded((ex) => {
16
+ const split = asset.split('/');
17
+ const keysToExpand = split.map((_, i) => {
18
+ return split.slice(0, i).join('/');
19
+ });
20
+ const newState = {
21
+ ...ex,
22
+ };
23
+ for (const key of keysToExpand) {
24
+ newState[key] = true;
25
+ }
26
+ return newState;
27
+ });
28
+ }, [setAssetFoldersExpanded, setCanvasContent]);
29
+ };
30
+ exports.useSelectAsset = useSelectAsset;
@@ -0,0 +1,3 @@
1
+ export declare const markErrorAsLoggedByServer: (error: object) => void;
2
+ export declare const markErrorMessageAsLoggedByServer: (message: string) => void;
3
+ export declare const wasErrorLoggedByServer: (error: Error) => boolean;
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.wasErrorLoggedByServer = exports.markErrorMessageAsLoggedByServer = exports.markErrorAsLoggedByServer = void 0;
4
+ const errorsLoggedByServer = new WeakSet();
5
+ const errorMessagesLoggedByServer = new Set();
6
+ const maxLoggedErrorMessages = 100;
7
+ const rememberServerLoggedMessage = (message) => {
8
+ if (errorMessagesLoggedByServer.size >= maxLoggedErrorMessages) {
9
+ errorMessagesLoggedByServer.clear();
10
+ }
11
+ errorMessagesLoggedByServer.add(message);
12
+ };
13
+ const markErrorAsLoggedByServer = (error) => {
14
+ errorsLoggedByServer.add(error);
15
+ };
16
+ exports.markErrorAsLoggedByServer = markErrorAsLoggedByServer;
17
+ const markErrorMessageAsLoggedByServer = (message) => {
18
+ if (message.trim() === '') {
19
+ return;
20
+ }
21
+ rememberServerLoggedMessage(message);
22
+ };
23
+ exports.markErrorMessageAsLoggedByServer = markErrorMessageAsLoggedByServer;
24
+ const wasErrorLoggedByServer = (error) => {
25
+ if (errorsLoggedByServer.has(error)) {
26
+ return true;
27
+ }
28
+ const message = typeof error.message === 'string' ? error.message : null;
29
+ const stack = typeof error.stack === 'string' ? error.stack : null;
30
+ if (message && errorMessagesLoggedByServer.has(message)) {
31
+ return true;
32
+ }
33
+ if (stack) {
34
+ for (const serverLoggedMessage of errorMessagesLoggedByServer) {
35
+ if (stack.includes(serverLoggedMessage)) {
36
+ return true;
37
+ }
38
+ }
39
+ }
40
+ return false;
41
+ };
42
+ exports.wasErrorLoggedByServer = wasErrorLoggedByServer;
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getErrorRecord = void 0;
4
4
  exports.listenToRuntimeErrors = listenToRuntimeErrors;
5
5
  const url_state_1 = require("../../helpers/url-state");
6
+ const error_origin_1 = require("../error-origin");
6
7
  const Overlay_1 = require("../remotion-overlay/Overlay");
7
8
  const format_warning_1 = require("./effects/format-warning");
8
9
  const proxy_console_1 = require("./effects/proxy-console");
@@ -60,13 +61,16 @@ function listenToRuntimeErrors(crash) {
60
61
  if (d.type === 'webpack-error') {
61
62
  const { message, frames } = d;
62
63
  const data = (0, format_warning_1.massageWarning)(message, frames);
63
- crashWithFramesRunTime({
64
+ const error = {
64
65
  message: data.message,
65
66
  stack: data.stack,
66
67
  name: '',
67
- });
68
+ };
69
+ (0, error_origin_1.markErrorAsLoggedByServer)(error);
70
+ crashWithFramesRunTime(error);
68
71
  }
69
72
  if (d.type === 'build-error') {
73
+ (0, error_origin_1.markErrorAsLoggedByServer)(d.error);
70
74
  crashWithFramesRunTime(d.error);
71
75
  }
72
76
  });
@@ -2,10 +2,13 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ErrorLoader = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const studio_shared_1 = require("@remotion/studio-shared");
5
6
  const react_1 = require("react");
7
+ const error_origin_1 = require("../error-origin");
6
8
  const listen_to_runtime_errors_1 = require("../react-overlay/listen-to-runtime-errors");
7
9
  const ErrorDisplay_1 = require("./ErrorDisplay");
8
10
  const ErrorTitle_1 = require("./ErrorTitle");
11
+ const log_studio_error_1 = require("./log-studio-error");
9
12
  const container = {
10
13
  width: '100%',
11
14
  maxWidth: 1000,
@@ -21,6 +24,32 @@ const errorWhileErrorStyle = {
21
24
  lineHeight: 1.5,
22
25
  whiteSpace: 'pre',
23
26
  };
27
+ const shouldLogError = (error) => {
28
+ return (!(0, error_origin_1.wasErrorLoggedByServer)(error) && (0, studio_shared_1.getLocationFromBuildError)(error) === null);
29
+ };
30
+ const shouldIncludeFrameInServerLog = (frame) => {
31
+ var _a, _b, _c, _d;
32
+ return !(((_a = frame.originalFileName) === null || _a === void 0 ? void 0 : _a.includes('node_modules')) ||
33
+ ((_b = frame.originalFileName) === null || _b === void 0 ? void 0 : _b.startsWith('webpack/')) ||
34
+ ((_c = frame.originalFileName) === null || _c === void 0 ? void 0 : _c.includes('/bundler/dist/fast-refresh/')) ||
35
+ ((_d = frame.originalFileName) === null || _d === void 0 ? void 0 : _d.includes('bundler/dist/fast-refresh/')));
36
+ };
37
+ const logSymbolicatedStudioError = (record) => {
38
+ const name = typeof record.error.name === 'string' ? record.error.name : null;
39
+ const message = typeof record.error.message === 'string' ? record.error.message : '';
40
+ const filteredStackFrames = record.stackFrames.filter(shouldIncludeFrameInServerLog);
41
+ const stackFrames = filteredStackFrames.length > 0
42
+ ? filteredStackFrames
43
+ : record.stackFrames[0]
44
+ ? [record.stackFrames[0]]
45
+ : [];
46
+ (0, log_studio_error_1.logStudioErrorData)({
47
+ name,
48
+ message,
49
+ stack: typeof record.error.stack === 'string' ? record.error.stack : null,
50
+ symbolicatedStackFrames: stackFrames.length > 0 ? stackFrames : null,
51
+ });
52
+ };
24
53
  const ErrorLoader = ({ error, keyboardShortcuts, onRetry, canHaveDismissButton, calculateMetadata, }) => {
25
54
  const [state, setState] = (0, react_1.useState)({
26
55
  type: 'loading',
@@ -29,18 +58,27 @@ const ErrorLoader = ({ error, keyboardShortcuts, onRetry, canHaveDismissButton,
29
58
  (0, listen_to_runtime_errors_1.getErrorRecord)(error)
30
59
  .then((record) => {
31
60
  if (record) {
61
+ if (shouldLogError(error)) {
62
+ logSymbolicatedStudioError(record);
63
+ }
32
64
  setState({
33
65
  type: 'symbolicated',
34
66
  record,
35
67
  });
36
68
  }
37
69
  else {
70
+ if (shouldLogError(error)) {
71
+ (0, log_studio_error_1.logStudioError)(error);
72
+ }
38
73
  setState({
39
74
  type: 'no-record',
40
75
  });
41
76
  }
42
77
  })
43
78
  .catch((err) => {
79
+ if (shouldLogError(error)) {
80
+ (0, log_studio_error_1.logStudioError)(error);
81
+ }
44
82
  setState({
45
83
  err,
46
84
  type: 'error',
@@ -4,7 +4,7 @@ exports.ShortcutHint = exports.cmdOrCtrlCharacter = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const use_keybinding_1 = require("../../helpers/use-keybinding");
7
- exports.cmdOrCtrlCharacter = window.navigator.platform.startsWith('Mac')
7
+ exports.cmdOrCtrlCharacter = typeof window !== 'undefined' && window.navigator.platform.startsWith('Mac')
8
8
  ? '⌘'
9
9
  : 'Ctrl';
10
10
  const container = {
@@ -0,0 +1,3 @@
1
+ import type { LogStudioErrorRequest } from '@remotion/studio-shared';
2
+ export declare const logStudioErrorData: (data: LogStudioErrorRequest) => void;
3
+ export declare const logStudioError: (error: Error) => void;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.logStudioError = exports.logStudioErrorData = void 0;
4
+ const call_api_1 = require("../../components/call-api");
5
+ const loggedErrors = new Set();
6
+ const maxLoggedErrors = 100;
7
+ const logStudioErrorData = (data) => {
8
+ const key = JSON.stringify([data.name, data.message, data.stack]);
9
+ if (loggedErrors.has(key)) {
10
+ return;
11
+ }
12
+ if (loggedErrors.size >= maxLoggedErrors) {
13
+ loggedErrors.clear();
14
+ }
15
+ loggedErrors.add(key);
16
+ (0, call_api_1.callApi)('/api/log-studio-error', data).catch(() => undefined);
17
+ };
18
+ exports.logStudioErrorData = logStudioErrorData;
19
+ const logStudioError = (error) => {
20
+ (0, exports.logStudioErrorData)({
21
+ name: typeof error.name === 'string' ? error.name : null,
22
+ message: typeof error.message === 'string' ? error.message : '',
23
+ stack: typeof error.stack === 'string' ? error.stack : null,
24
+ symbolicatedStackFrames: null,
25
+ });
26
+ };
27
+ exports.logStudioError = logStudioError;