@remotion/studio 4.0.519 → 4.0.521

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/dist/api/shut-down-studio.d.ts +6 -0
  2. package/dist/api/shut-down-studio.js +23 -0
  3. package/dist/api/visual-control.js +2 -2
  4. package/dist/components/AudioWaveform.js +16 -7
  5. package/dist/components/Canvas.js +114 -48
  6. package/dist/components/CaptionInspector.d.ts +1 -0
  7. package/dist/components/CaptionInspector.js +43 -2
  8. package/dist/components/CaptionTextEditor.js +1 -1
  9. package/dist/components/CompositionSelector.js +41 -34
  10. package/dist/components/CompositionSelectorItem.d.ts +7 -0
  11. package/dist/components/CompositionSelectorItem.js +344 -73
  12. package/dist/components/CurrentCompositionSideEffects.js +5 -0
  13. package/dist/components/ElementInstallConfirmation.d.ts +2 -23
  14. package/dist/components/ElementInstallConfirmation.js +89 -65
  15. package/dist/components/ElementLibraryModal.js +3 -1
  16. package/dist/components/FpsCounter.js +1 -1
  17. package/dist/components/FramePersistor.js +1 -1
  18. package/dist/components/InlineCaptionInspector.js +37 -1
  19. package/dist/components/InspectorPanel/ElementLibraryButton.js +3 -18
  20. package/dist/components/InspectorPanel/SequenceSelectionInspector.js +4 -3
  21. package/dist/components/InspectorPanel/use-composition-actions.js +5 -8
  22. package/dist/components/InspectorSequenceSection.js +1 -4
  23. package/dist/components/Menu/MenuSubItem.js +1 -1
  24. package/dist/components/ModalContainer.d.ts +1 -0
  25. package/dist/components/ModalContainer.js +2 -2
  26. package/dist/components/ModalHeader.js +5 -1
  27. package/dist/components/Modals.js +1 -1
  28. package/dist/components/NewComposition/NewComposition.js +2 -2
  29. package/dist/components/PlayPause.js +2 -13
  30. package/dist/components/PreviewToolbar.js +1 -1
  31. package/dist/components/QuickSwitcher/QuickSwitcherContent.js +29 -15
  32. package/dist/components/QuickSwitcher/QuickSwitcherResult.d.ts +14 -1
  33. package/dist/components/QuickSwitcher/QuickSwitcherResult.js +64 -9
  34. package/dist/components/QuickSwitcher/asset-search.d.ts +0 -1
  35. package/dist/components/QuickSwitcher/asset-search.js +1 -16
  36. package/dist/components/QuickSwitcher/composition-search.d.ts +16 -0
  37. package/dist/components/QuickSwitcher/composition-search.js +136 -0
  38. package/dist/components/RenderButton.js +2 -2
  39. package/dist/components/RenderModal/RenderStatusModal.js +7 -1
  40. package/dist/components/RenderModal/ServerRenderModal.js +1 -1
  41. package/dist/components/RenderModal/WebRenderModal.js +1 -1
  42. package/dist/components/RenderQueue/ClientRenderQueueProcessor.js +1 -1
  43. package/dist/components/ResetZoomButton.js +17 -2
  44. package/dist/components/SelectedOutlineElement.js +10 -30
  45. package/dist/components/SettingsModal.js +8 -5
  46. package/dist/components/TimeValue.js +36 -7
  47. package/dist/components/Timeline/Timeline.d.ts +1 -1
  48. package/dist/components/Timeline/Timeline.js +33 -20
  49. package/dist/components/Timeline/TimelineAssetField.d.ts +0 -1
  50. package/dist/components/Timeline/TimelineAssetField.js +17 -9
  51. package/dist/components/Timeline/TimelineCollapseToggle.js +1 -1
  52. package/dist/components/Timeline/TimelineDeleteKeybindings.js +5 -90
  53. package/dist/components/Timeline/TimelineDragHandler.js +18 -8
  54. package/dist/components/Timeline/TimelineFontWeightField.d.ts +11 -0
  55. package/dist/components/Timeline/TimelineFontWeightField.js +65 -0
  56. package/dist/components/Timeline/TimelineInOutDragHandler.js +2 -3
  57. package/dist/components/Timeline/TimelineLayerChildren.d.ts +21 -0
  58. package/dist/components/Timeline/TimelineLayerChildren.js +129 -0
  59. package/dist/components/Timeline/TimelineNumberField.js +13 -5
  60. package/dist/components/Timeline/TimelinePinchZoom.js +14 -4
  61. package/dist/components/Timeline/TimelinePlayCursorSyncer.js +8 -4
  62. package/dist/components/Timeline/TimelinePrimitiveFieldValue.js +4 -0
  63. package/dist/components/Timeline/TimelineSequence.js +54 -73
  64. package/dist/components/Timeline/TimelineSequenceItem.js +16 -36
  65. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +22 -10
  66. package/dist/components/Timeline/TimelineSlider.js +2 -2
  67. package/dist/components/Timeline/TimelineTickFormatProvider.d.ts +8 -0
  68. package/dist/components/Timeline/TimelineTickFormatProvider.js +16 -0
  69. package/dist/components/Timeline/TimelineTimeIndicators.js +7 -3
  70. package/dist/components/Timeline/TimelineVideoInfo.js +7 -3
  71. package/dist/components/Timeline/TimelineWidthProvider.js +15 -8
  72. package/dist/components/Timeline/TimelineZoomControls.js +25 -8
  73. package/dist/components/Timeline/delete-selected-timeline-item.js +2 -2
  74. package/dist/components/Timeline/timeline-field-display-utils.js +1 -0
  75. package/dist/components/Timeline/timeline-scroll-logic.d.ts +1 -0
  76. package/dist/components/Timeline/timeline-scroll-logic.js +21 -17
  77. package/dist/components/Timeline/use-delete-timeline-items.d.ts +1 -0
  78. package/dist/components/Timeline/use-delete-timeline-items.js +118 -0
  79. package/dist/components/Timeline/use-timeline-asset-drop.js +8 -14
  80. package/dist/components/UpdateStatusContext.d.ts +5 -0
  81. package/dist/components/UpdateStatusContext.js +53 -2
  82. package/dist/components/UpdatesSettings.js +25 -4
  83. package/dist/components/WebMcp.js +87 -8
  84. package/dist/components/ZoomPersistor.js +2 -2
  85. package/dist/components/composition-drag-data.d.ts +36 -0
  86. package/dist/components/composition-drag-data.js +232 -0
  87. package/dist/components/composition-selector-drag-data.d.ts +27 -0
  88. package/dist/components/composition-selector-drag-data.js +80 -0
  89. package/dist/components/drop-handler-data.d.ts +2 -1
  90. package/dist/components/drop-handler-data.js +6 -4
  91. package/dist/components/effect-drag-and-drop.d.ts +2 -5
  92. package/dist/components/handle-drop.js +6 -2
  93. package/dist/components/import-assets.d.ts +7 -14
  94. package/dist/components/import-assets.js +11 -1
  95. package/dist/components/parse-caption-file.d.ts +5 -0
  96. package/dist/components/parse-caption-file.js +63 -0
  97. package/dist/error-overlay/current-error.d.ts +13 -0
  98. package/dist/error-overlay/current-error.js +21 -0
  99. package/dist/error-overlay/remotion-overlay/ErrorLoader.js +5 -1
  100. package/dist/esm/chunk-emw4k5b0.js +99527 -0
  101. package/dist/esm/{chunk-1fkq5bfq.js → chunk-vkrvnx2h.js} +20116 -16283
  102. package/dist/esm/index.mjs +27 -9
  103. package/dist/esm/internals.mjs +17408 -13426
  104. package/dist/esm/previewEntry.mjs +17285 -13216
  105. package/dist/esm/renderEntry.mjs +1 -1
  106. package/dist/helpers/create-folder-tree.js +2 -5
  107. package/dist/helpers/document-title.d.ts +2 -0
  108. package/dist/helpers/document-title.js +14 -3
  109. package/dist/helpers/get-preview-file-type.js +22 -3
  110. package/dist/helpers/get-timeline-max-zoom.d.ts +34 -28
  111. package/dist/helpers/get-timeline-max-zoom.js +46 -29
  112. package/dist/helpers/inserted-element-selection.d.ts +2 -1
  113. package/dist/helpers/install-fiber-sequence-order-observer.d.ts +37 -0
  114. package/dist/helpers/install-fiber-sequence-order-observer.js +109 -0
  115. package/dist/helpers/open-in-editor.js +2 -1
  116. package/dist/helpers/use-menu-structure.js +2 -2
  117. package/dist/helpers/use-runtime-values.d.ts +1 -1
  118. package/dist/helpers/use-runtime-values.js +5 -4
  119. package/dist/helpers/use-sync-external-store.d.ts +3 -0
  120. package/dist/helpers/use-sync-external-store.js +5 -0
  121. package/dist/index.d.ts +1 -0
  122. package/dist/index.js +3 -1
  123. package/dist/previewEntry.js +2 -0
  124. package/dist/state/modals.d.ts +16 -2
  125. package/dist/state/timeline-sequence-hover.js +3 -2
  126. package/dist/state/timeline-zoom.d.ts +0 -1
  127. package/dist/state/timeline-zoom.js +13 -6
  128. package/package.json +17 -17
  129. package/dist/helpers/sort-by-nonce-history.d.ts +0 -1
  130. package/dist/helpers/sort-by-nonce-history.js +0 -6
@@ -2,9 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CompositionSelectorItem = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
- const studio_protocol_1 = require("@remotion/studio-protocol");
6
- const studio_shared_1 = require("@remotion/studio-shared");
7
5
  const react_1 = require("react");
6
+ const browser_studio_operations_1 = require("../helpers/browser-studio-operations");
8
7
  const client_id_1 = require("../helpers/client-id");
9
8
  const colors_1 = require("../helpers/colors");
10
9
  const hoverable_1 = require("../helpers/hoverable");
@@ -12,7 +11,9 @@ const noop_1 = require("../helpers/noop");
12
11
  const sidebar_scroll_into_view_1 = require("../helpers/sidebar-scroll-into-view");
13
12
  const folder_1 = require("../icons/folder");
14
13
  const modals_1 = require("../state/modals");
14
+ const composition_drag_data_1 = require("./composition-drag-data");
15
15
  const composition_menu_items_1 = require("./composition-menu-items");
16
+ const composition_selector_drag_data_1 = require("./composition-selector-drag-data");
16
17
  const CompositionContextButton_1 = require("./CompositionContextButton");
17
18
  const CompositionOrStillIcon_1 = require("./CompositionOrStillIcon");
18
19
  const ContextMenu_1 = require("./ContextMenu");
@@ -57,7 +58,56 @@ const iconStyle = {
57
58
  height: 18,
58
59
  flexShrink: 0,
59
60
  };
60
- const CompositionSelectorItem = ({ item, level, currentComposition, tabIndex, selectComposition, toggleFolder, clearRootDragHover, }) => {
61
+ const reorderWrapper = {
62
+ position: 'relative',
63
+ };
64
+ const reorderLineBase = {
65
+ backgroundColor: colors_1.TIMELINE_BLUE,
66
+ height: 2,
67
+ left: 0,
68
+ pointerEvents: 'none',
69
+ position: 'absolute',
70
+ right: 0,
71
+ zIndex: 1,
72
+ };
73
+ const folderAutoExpansionDelay = 700;
74
+ const itemToDescriptor = (item) => {
75
+ return item.type === 'composition'
76
+ ? { type: 'composition', compositionId: item.composition.id }
77
+ : {
78
+ type: 'folder',
79
+ folderName: item.folderName,
80
+ parentName: item.parentName,
81
+ };
82
+ };
83
+ const itemsAreEqual = (left, right) => {
84
+ if (left.type === 'composition') {
85
+ return (right.type === 'composition' && left.compositionId === right.compositionId);
86
+ }
87
+ return (right.type === 'folder' &&
88
+ left.folderName === right.folderName &&
89
+ left.parentName === right.parentName);
90
+ };
91
+ const getFolderPath = ({ folderName, parentName, }) => {
92
+ return [parentName, folderName].filter(Boolean).join('/');
93
+ };
94
+ const wouldMoveFolderIntoItself = ({ activeDrag, destinationParentFolderPath, }) => {
95
+ if (activeDrag.item.type !== 'folder' ||
96
+ destinationParentFolderPath === null) {
97
+ return false;
98
+ }
99
+ const sourceFolderPath = getFolderPath(activeDrag.item);
100
+ return (destinationParentFolderPath === sourceFolderPath ||
101
+ destinationParentFolderPath.startsWith(`${sourceFolderPath}/`));
102
+ };
103
+ const canMoveIntoFolder = ({ activeDrag, destinationFolderPath, }) => {
104
+ return (activeDrag.parentFolderPath !== destinationFolderPath &&
105
+ !wouldMoveFolderIntoItself({
106
+ activeDrag,
107
+ destinationParentFolderPath: destinationFolderPath,
108
+ }));
109
+ };
110
+ const CompositionSelectorItem = ({ item, level, currentComposition, tabIndex, selectComposition, toggleFolder, clearRootDragHover, canReorder, activeDragRef, parentFolderPath, previousSibling, nextSibling, }) => {
61
111
  const selected = (0, react_1.useMemo)(() => {
62
112
  if (item.type === 'composition') {
63
113
  return currentComposition === item.composition.id;
@@ -65,7 +115,30 @@ const CompositionSelectorItem = ({ item, level, currentComposition, tabIndex, se
65
115
  return false;
66
116
  }, [item, currentComposition]);
67
117
  const [isDragging, setIsDragging] = (0, react_1.useState)(false);
68
- const [dragHovered, setDragHovered] = (0, react_1.useState)(false);
118
+ const [dropPosition, setDropPosition] = (0, react_1.useState)(null);
119
+ const dropPositionRef = (0, react_1.useRef)(null);
120
+ const folderExpansionTimer = (0, react_1.useRef)(null);
121
+ const folderExpansionRequested = (0, react_1.useRef)(false);
122
+ const cancelFolderExpansion = (0, react_1.useCallback)(() => {
123
+ if (folderExpansionTimer.current !== null) {
124
+ window.clearTimeout(folderExpansionTimer.current);
125
+ folderExpansionTimer.current = null;
126
+ }
127
+ }, []);
128
+ const updateDropPosition = (0, react_1.useCallback)((position) => {
129
+ dropPositionRef.current = position;
130
+ setDropPosition(position);
131
+ }, []);
132
+ (0, react_1.useEffect)(() => {
133
+ return cancelFolderExpansion;
134
+ }, [cancelFolderExpansion]);
135
+ const folderIsExpanded = item.type === 'folder' && item.expanded;
136
+ (0, react_1.useEffect)(() => {
137
+ if (folderIsExpanded) {
138
+ folderExpansionRequested.current = false;
139
+ cancelFolderExpansion();
140
+ }
141
+ }, [cancelFolderExpansion, folderIsExpanded]);
69
142
  const compositionRowRef = (0, react_1.useRef)(null);
70
143
  const compositionId = item.type === 'composition' ? item.composition.id : null;
71
144
  (0, react_1.useLayoutEffect)(() => {
@@ -79,7 +152,7 @@ const CompositionSelectorItem = ({ item, level, currentComposition, tabIndex, se
79
152
  });
80
153
  }, [compositionId, selected]);
81
154
  const style = (0, react_1.useMemo)(() => {
82
- const idleBackground = dragHovered
155
+ const idleBackground = dropPosition === 'inside'
83
156
  ? colors_1.WHITE_ALPHA_12
84
157
  : selected
85
158
  ? colors_1.WHITE_ALPHA_06
@@ -88,13 +161,22 @@ const CompositionSelectorItem = ({ item, level, currentComposition, tabIndex, se
88
161
  ...itemStyle,
89
162
  ...(0, hoverable_1.hoverableStyle)({
90
163
  idleBackground,
91
- hoverBackground: dragHovered ? colors_1.WHITE_ALPHA_12 : colors_1.WHITE_ALPHA_06,
164
+ hoverBackground: dropPosition === 'inside' ? colors_1.WHITE_ALPHA_12 : colors_1.WHITE_ALPHA_06,
92
165
  idleColor: selected ? colors_1.WHITE : colors_1.LIGHT_TEXT,
93
166
  hoverColor: colors_1.WHITE,
94
167
  }),
95
168
  paddingLeft: 12 + level * 8,
96
169
  };
97
- }, [dragHovered, level, selected]);
170
+ }, [dropPosition, level, selected]);
171
+ const reorderLineStyle = (0, react_1.useMemo)(() => {
172
+ if (dropPosition !== 'before' && dropPosition !== 'after') {
173
+ return null;
174
+ }
175
+ return {
176
+ ...reorderLineBase,
177
+ ...(dropPosition === 'before' ? { top: -1 } : { bottom: -1 }),
178
+ };
179
+ }, [dropPosition]);
98
180
  const onClick = (0, react_1.useCallback)((evt) => {
99
181
  evt.preventDefault();
100
182
  if (item.type === 'composition') {
@@ -147,88 +229,185 @@ const CompositionSelectorItem = ({ item, level, currentComposition, tabIndex, se
147
229
  resolvedLocation,
148
230
  setSelectedModal,
149
231
  ]);
150
- const onCompositionDragStart = (0, react_1.useCallback)((event) => {
151
- var _a, _b, _c, _d;
152
- if (item.type !== 'composition' || window.remotion_isReadOnlyStudio) {
232
+ const onItemDragStart = (0, react_1.useCallback)((event) => {
233
+ var _a, _b, _c, _d, _e;
234
+ if (window.remotion_isReadOnlyStudio) {
153
235
  event.preventDefault();
154
236
  return;
155
237
  }
238
+ const itemDescriptor = itemToDescriptor(item);
239
+ activeDragRef.current = {
240
+ item: itemDescriptor,
241
+ parentFolderPath,
242
+ };
156
243
  setIsDragging(true);
157
244
  event.dataTransfer.effectAllowed = 'copyMove';
158
- const dragData = studio_protocol_1.StudioProtocolInternals.makeDragData({
159
- type: 'composition',
160
- compositionFile: (_a = resolvedLocation === null || resolvedLocation === void 0 ? void 0 : resolvedLocation.source) !== null && _a !== void 0 ? _a : null,
161
- compositionId: item.composition.id,
162
- width: (_b = item.composition.width) !== null && _b !== void 0 ? _b : null,
163
- height: (_c = item.composition.height) !== null && _c !== void 0 ? _c : null,
164
- durationInFrames: (_d = item.composition.durationInFrames) !== null && _d !== void 0 ? _d : null,
245
+ const selectorDragData = (0, composition_selector_drag_data_1.makeCompositionSelectorDragData)({
246
+ item: itemDescriptor,
247
+ sourceFile: (_a = resolvedLocation === null || resolvedLocation === void 0 ? void 0 : resolvedLocation.source) !== null && _a !== void 0 ? _a : null,
165
248
  });
166
- event.dataTransfer.setData(dragData.mimeType, dragData.payload);
167
- }, [item, resolvedLocation === null || resolvedLocation === void 0 ? void 0 : resolvedLocation.source]);
168
- const onCompositionDragEnd = (0, react_1.useCallback)(() => {
249
+ event.dataTransfer.setData(selectorDragData.mimeType, selectorDragData.payload);
250
+ if (item.type === 'composition') {
251
+ const browserStudioOperations = (0, browser_studio_operations_1.getBrowserStudioOperations)();
252
+ const compositionDragData = (0, composition_drag_data_1.makeCompositionDragData)({
253
+ compositionFile: browserStudioOperations === null
254
+ ? ((_b = resolvedLocation === null || resolvedLocation === void 0 ? void 0 : resolvedLocation.source) !== null && _b !== void 0 ? _b : null)
255
+ : browserStudioOperations.getCompositionFile(item.composition.id),
256
+ compositionId: item.composition.id,
257
+ width: (_c = item.composition.width) !== null && _c !== void 0 ? _c : null,
258
+ height: (_d = item.composition.height) !== null && _d !== void 0 ? _d : null,
259
+ durationInFrames: (_e = item.composition.durationInFrames) !== null && _e !== void 0 ? _e : null,
260
+ });
261
+ event.dataTransfer.setData(compositionDragData.mimeType, compositionDragData.payload);
262
+ }
263
+ }, [activeDragRef, item, parentFolderPath, resolvedLocation === null || resolvedLocation === void 0 ? void 0 : resolvedLocation.source]);
264
+ const onItemDragEnd = (0, react_1.useCallback)(() => {
265
+ activeDragRef.current = null;
266
+ cancelFolderExpansion();
169
267
  setIsDragging(false);
170
- }, []);
171
- const onFolderDragOver = (0, react_1.useCallback)((event) => {
172
- var _a;
268
+ updateDropPosition(null);
269
+ }, [activeDragRef, cancelFolderExpansion, updateDropPosition]);
270
+ const getDropPosition = (0, react_1.useCallback)((event) => {
271
+ const activeDrag = activeDragRef.current;
272
+ if (activeDrag === null) {
273
+ return null;
274
+ }
275
+ if (!canReorder) {
276
+ if (item.type !== 'folder') {
277
+ return null;
278
+ }
279
+ return canMoveIntoFolder({
280
+ activeDrag,
281
+ destinationFolderPath: getFolderPath(item),
282
+ })
283
+ ? 'inside'
284
+ : null;
285
+ }
286
+ const { top, height } = event.currentTarget.getBoundingClientRect();
287
+ const progress = height === 0 ? 0.5 : (event.clientY - top) / height;
288
+ const position = item.type === 'composition'
289
+ ? progress < 0.5
290
+ ? 'before'
291
+ : 'after'
292
+ : progress < 0.25
293
+ ? 'before'
294
+ : progress > 0.75
295
+ ? 'after'
296
+ : 'inside';
297
+ const target = itemToDescriptor(item);
298
+ if (itemsAreEqual(activeDrag.item, target)) {
299
+ return null;
300
+ }
301
+ if (position === 'before' &&
302
+ previousSibling !== null &&
303
+ itemsAreEqual(activeDrag.item, itemToDescriptor(previousSibling))) {
304
+ return null;
305
+ }
306
+ if (position === 'after' &&
307
+ nextSibling !== null &&
308
+ itemsAreEqual(activeDrag.item, itemToDescriptor(nextSibling))) {
309
+ return null;
310
+ }
311
+ if (position === 'inside' && item.type === 'folder') {
312
+ return canMoveIntoFolder({
313
+ activeDrag,
314
+ destinationFolderPath: getFolderPath(item),
315
+ })
316
+ ? position
317
+ : null;
318
+ }
319
+ return wouldMoveFolderIntoItself({
320
+ activeDrag,
321
+ destinationParentFolderPath: parentFolderPath,
322
+ })
323
+ ? null
324
+ : position;
325
+ }, [
326
+ activeDragRef,
327
+ canReorder,
328
+ item,
329
+ nextSibling,
330
+ parentFolderPath,
331
+ previousSibling,
332
+ ]);
333
+ const scheduleFolderExpansion = (0, react_1.useCallback)(() => {
173
334
  if (item.type !== 'folder' ||
174
- window.remotion_isReadOnlyStudio ||
175
- ((_a = studio_protocol_1.StudioProtocolInternals.getDragPreviewMetadata(event.dataTransfer.types)) === null || _a === void 0 ? void 0 : _a.type) !== 'composition') {
335
+ item.expanded ||
336
+ folderExpansionTimer.current !== null ||
337
+ folderExpansionRequested.current) {
176
338
  return;
177
339
  }
178
- event.preventDefault();
179
- event.stopPropagation();
180
- event.dataTransfer.dropEffect = 'move';
181
- clearRootDragHover();
182
- setDragHovered(true);
183
- }, [clearRootDragHover, item]);
184
- const onFolderDragLeave = (0, react_1.useCallback)(() => {
185
- setDragHovered(false);
186
- }, []);
187
- const onFolderChildListDragOver = (0, react_1.useCallback)((event) => {
188
- var _a;
189
- if (item.type !== 'folder' ||
190
- window.remotion_isReadOnlyStudio ||
191
- ((_a = studio_protocol_1.StudioProtocolInternals.getDragPreviewMetadata(event.dataTransfer.types)) === null || _a === void 0 ? void 0 : _a.type) !== 'composition') {
340
+ const activeDrag = activeDragRef.current;
341
+ if (activeDrag === null ||
342
+ !canMoveIntoFolder({
343
+ activeDrag,
344
+ destinationFolderPath: getFolderPath(item),
345
+ })) {
192
346
  return;
193
347
  }
194
- event.preventDefault();
195
- event.stopPropagation();
196
- event.dataTransfer.dropEffect = 'move';
197
- clearRootDragHover();
198
- }, [clearRootDragHover, item]);
199
- const onFolderDrop = (0, react_1.useCallback)(async (event) => {
200
- if (item.type !== 'folder' || window.remotion_isReadOnlyStudio) {
348
+ folderExpansionTimer.current = window.setTimeout(() => {
349
+ folderExpansionTimer.current = null;
350
+ const currentActiveDrag = activeDragRef.current;
351
+ if (currentActiveDrag === null ||
352
+ !canMoveIntoFolder({
353
+ activeDrag: currentActiveDrag,
354
+ destinationFolderPath: getFolderPath(item),
355
+ })) {
356
+ return;
357
+ }
358
+ folderExpansionRequested.current = true;
359
+ toggleFolder(item.folderName, item.parentName);
360
+ }, folderAutoExpansionDelay);
361
+ }, [activeDragRef, item, toggleFolder]);
362
+ const onRowDragOver = (0, react_1.useCallback)((event) => {
363
+ if (window.remotion_isReadOnlyStudio ||
364
+ !(0, composition_selector_drag_data_1.hasCompositionSelectorDragData)(event.dataTransfer.types)) {
201
365
  return;
202
366
  }
203
- const parsed = studio_protocol_1.StudioProtocolInternals.parseDragData(event.dataTransfer);
204
- if ((parsed === null || parsed === void 0 ? void 0 : parsed.type) !== 'composition') {
367
+ const position = getDropPosition(event);
368
+ if (position === null) {
369
+ cancelFolderExpansion();
370
+ updateDropPosition(null);
371
+ event.stopPropagation();
205
372
  return;
206
373
  }
207
- const compositionDragData = parsed.data;
374
+ if (position === 'inside') {
375
+ scheduleFolderExpansion();
376
+ }
377
+ else {
378
+ cancelFolderExpansion();
379
+ }
208
380
  event.preventDefault();
209
381
  event.stopPropagation();
382
+ event.dataTransfer.dropEffect = 'move';
210
383
  clearRootDragHover();
211
- setDragHovered(false);
212
- const isAlreadyDirectChild = item.items.some((child) => {
213
- return (child.type === 'composition' &&
214
- child.composition.id === compositionDragData.compositionId);
215
- });
216
- if (isAlreadyDirectChild) {
217
- return;
218
- }
219
- const notification = (0, NotificationCenter_1.showNotification)(`Moving ${compositionDragData.compositionId}...`, null);
220
- const controller = new AbortController();
384
+ updateDropPosition(position);
385
+ }, [
386
+ cancelFolderExpansion,
387
+ clearRootDragHover,
388
+ getDropPosition,
389
+ scheduleFolderExpansion,
390
+ updateDropPosition,
391
+ ]);
392
+ const onRowDragLeave = (0, react_1.useCallback)(() => {
393
+ cancelFolderExpansion();
394
+ updateDropPosition(null);
395
+ }, [cancelFolderExpansion, updateDropPosition]);
396
+ const moveItem = (0, react_1.useCallback)(async ({ destination, dragData, }) => {
397
+ const label = dragData.item.type === 'composition'
398
+ ? dragData.item.compositionId
399
+ : dragData.item.folderName;
400
+ const notification = (0, NotificationCenter_1.showNotification)(`Moving ${label}...`, null);
221
401
  try {
222
402
  const result = await (0, actions_1.applyCodemod)({
223
403
  codemod: {
224
- type: 'move-composition-to-folder',
225
- idToMove: compositionDragData.compositionId,
226
- folderName: item.folderName,
227
- parentName: item.parentName,
404
+ type: 'move-composition-or-folder',
405
+ source: dragData.item,
406
+ destination,
228
407
  },
229
408
  dryRun: false,
230
- signal: controller.signal,
231
- symbolicatedStack: (0, studio_shared_1.compositionDragDataToSymbolicatedStack)(compositionDragData),
409
+ signal: new AbortController().signal,
410
+ symbolicatedStack: (0, composition_selector_drag_data_1.compositionSelectorDragDataToSymbolicatedStack)(dragData),
232
411
  });
233
412
  if (result.success) {
234
413
  notification.dismiss();
@@ -236,23 +415,115 @@ const CompositionSelectorItem = ({ item, level, currentComposition, tabIndex, se
236
415
  else {
237
416
  notification.replaceContent(result.reason, 4000);
238
417
  }
239
- if (result.success && !item.expanded) {
418
+ if (result.success &&
419
+ destination.type === 'folder' &&
420
+ item.type === 'folder' &&
421
+ !item.expanded) {
240
422
  toggleFolder(item.folderName, item.parentName);
241
423
  }
242
424
  }
243
425
  catch (err) {
244
426
  notification.replaceContent(err instanceof Error ? err.message : String(err), 4000);
245
427
  }
246
- }, [clearRootDragHover, item, toggleFolder]);
428
+ }, [item, toggleFolder]);
429
+ const onRowDrop = (0, react_1.useCallback)(async (event) => {
430
+ cancelFolderExpansion();
431
+ const dragData = (0, composition_selector_drag_data_1.parseCompositionSelectorDragData)(event.dataTransfer);
432
+ const position = dropPositionRef.current;
433
+ if (dragData === null) {
434
+ return;
435
+ }
436
+ if (position === null) {
437
+ event.stopPropagation();
438
+ return;
439
+ }
440
+ event.preventDefault();
441
+ event.stopPropagation();
442
+ clearRootDragHover();
443
+ updateDropPosition(null);
444
+ await moveItem({
445
+ dragData,
446
+ destination: position === 'inside' && item.type === 'folder'
447
+ ? {
448
+ type: 'folder',
449
+ folderName: item.folderName,
450
+ parentName: item.parentName,
451
+ }
452
+ : {
453
+ type: position === 'before' ? 'before' : 'after',
454
+ target: itemToDescriptor(item),
455
+ },
456
+ });
457
+ }, [
458
+ cancelFolderExpansion,
459
+ clearRootDragHover,
460
+ item,
461
+ moveItem,
462
+ updateDropPosition,
463
+ ]);
464
+ const onFolderChildListDragOver = (0, react_1.useCallback)((event) => {
465
+ if (item.type !== 'folder' ||
466
+ window.remotion_isReadOnlyStudio ||
467
+ !(0, composition_selector_drag_data_1.hasCompositionSelectorDragData)(event.dataTransfer.types)) {
468
+ return;
469
+ }
470
+ const activeDrag = activeDragRef.current;
471
+ if (activeDrag === null ||
472
+ !canMoveIntoFolder({
473
+ activeDrag,
474
+ destinationFolderPath: getFolderPath(item),
475
+ })) {
476
+ event.stopPropagation();
477
+ return;
478
+ }
479
+ event.preventDefault();
480
+ event.stopPropagation();
481
+ event.dataTransfer.dropEffect = 'move';
482
+ clearRootDragHover();
483
+ }, [activeDragRef, clearRootDragHover, item]);
484
+ const onFolderChildListDrop = (0, react_1.useCallback)(async (event) => {
485
+ if (item.type !== 'folder' || window.remotion_isReadOnlyStudio) {
486
+ return;
487
+ }
488
+ const dragData = (0, composition_selector_drag_data_1.parseCompositionSelectorDragData)(event.dataTransfer);
489
+ if (dragData === null) {
490
+ return;
491
+ }
492
+ const activeDrag = activeDragRef.current;
493
+ if (activeDrag === null ||
494
+ !canMoveIntoFolder({
495
+ activeDrag,
496
+ destinationFolderPath: getFolderPath(item),
497
+ })) {
498
+ event.stopPropagation();
499
+ return;
500
+ }
501
+ event.preventDefault();
502
+ event.stopPropagation();
503
+ clearRootDragHover();
504
+ await moveItem({
505
+ dragData,
506
+ destination: {
507
+ type: 'folder',
508
+ folderName: item.folderName,
509
+ parentName: item.parentName,
510
+ },
511
+ });
512
+ }, [activeDragRef, clearRootDragHover, item, moveItem]);
247
513
  if (item.type === 'folder') {
514
+ const folderPath = getFolderPath(item);
248
515
  return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
249
- jsx_runtime_1.jsx(ContextMenu_1.ContextMenu, { getItems: getContextMenuItems, children: jsx_runtime_1.jsx(layout_1.Row, { align: "center", children: jsx_runtime_1.jsxs("div", { style: style, className: `__remotion-composition-selector-item ${hoverable_1.HOVERABLE_CLASS_NAME} ${hoverable_1.HOVER_GROUP_CLASS_NAME}`, tabIndex: tabIndex, onClick: onClick, onKeyDown: onKeyDown, onDragOver: onFolderDragOver, onDragLeave: onFolderDragLeave, onDrop: onFolderDrop, title: item.folderName, role: "button", children: [item.expanded ? (jsx_runtime_1.jsx(folder_1.ExpandedFolderIcon, { style: iconStyle, color: colors_1.CURRENT_COLOR })) : (jsx_runtime_1.jsx(folder_1.CollapsedFolderIcon, { color: colors_1.CURRENT_COLOR, style: iconStyle })), jsx_runtime_1.jsx(layout_1.Spacing, { x: 1 }), jsx_runtime_1.jsx("div", { style: labelStyle, children: item.folderName }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(CompositionContextButton_1.CompositionContextButton, { getItems: getContextMenuItems, visible: true, readOnlyStudio: window.remotion_isReadOnlyStudio })
250
- ] }) }) }), item.expanded ? (jsx_runtime_1.jsx("div", { onDragOver: onFolderChildListDragOver, onDrop: onFolderDrop, children: item.items.map((childItem) => {
251
- return (jsx_runtime_1.jsx(exports.CompositionSelectorItem, { currentComposition: currentComposition, selectComposition: selectComposition, item: childItem, tabIndex: tabIndex, level: level + 1, toggleFolder: toggleFolder, clearRootDragHover: clearRootDragHover }, childItem.key + childItem.type));
516
+ jsx_runtime_1.jsx(ContextMenu_1.ContextMenu, { getItems: getContextMenuItems, children: jsx_runtime_1.jsxs("div", { style: reorderWrapper, children: [reorderLineStyle ? (jsx_runtime_1.jsx("div", { "data-composition-reorder-line": true, style: reorderLineStyle })) : null, jsx_runtime_1.jsx(layout_1.Row, { align: "center", children: jsx_runtime_1.jsxs("div", { style: style, className: `__remotion-composition-selector-item ${hoverable_1.HOVERABLE_CLASS_NAME} ${hoverable_1.HOVER_GROUP_CLASS_NAME}`, tabIndex: tabIndex, onClick: onClick, onKeyDown: onKeyDown, draggable: !window.remotion_isReadOnlyStudio, onDragStart: onItemDragStart, onDragEnd: onItemDragEnd, onDragOver: onRowDragOver, onDragLeave: onRowDragLeave, onDrop: onRowDrop, title: item.folderName, role: "button", "aria-expanded": item.expanded, children: [item.expanded ? (jsx_runtime_1.jsx(folder_1.ExpandedFolderIcon, { style: iconStyle, color: colors_1.CURRENT_COLOR })) : (jsx_runtime_1.jsx(folder_1.CollapsedFolderIcon, { color: colors_1.CURRENT_COLOR, style: iconStyle })), jsx_runtime_1.jsx(layout_1.Spacing, { x: 1 }), jsx_runtime_1.jsx("div", { style: labelStyle, children: item.folderName }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(CompositionContextButton_1.CompositionContextButton, { getItems: getContextMenuItems, visible: true, readOnlyStudio: window.remotion_isReadOnlyStudio })
517
+ ] }) })
518
+ ] }) }), item.expanded ? (jsx_runtime_1.jsx("div", { onDragOver: onFolderChildListDragOver, onDrop: onFolderChildListDrop, children: item.items.map((childItem, index) => {
519
+ return (jsx_runtime_1.jsx(exports.CompositionSelectorItem, { currentComposition: currentComposition, selectComposition: selectComposition, item: childItem, tabIndex: tabIndex, level: level + 1, toggleFolder: toggleFolder, clearRootDragHover: clearRootDragHover, canReorder: canReorder, activeDragRef: activeDragRef, parentFolderPath: folderPath, previousSibling: index === 0 ? null : item.items[index - 1], nextSibling: index === item.items.length - 1
520
+ ? null
521
+ : item.items[index + 1] }, childItem.key + childItem.type));
252
522
  }) })) : null] }));
253
523
  }
254
- return (jsx_runtime_1.jsx(ContextMenu_1.ContextMenu, { getItems: getContextMenuItems, children: jsx_runtime_1.jsx(layout_1.Row, { align: "center", children: jsx_runtime_1.jsxs("a", { ref: compositionRowRef, style: style, tabIndex: tabIndex, onClick: onClick, onKeyDown: onKeyDown, draggable: !window.remotion_isReadOnlyStudio, onDragStart: onCompositionDragStart, onDragEnd: onCompositionDragEnd, type: "button", title: item.composition.id, className: `__remotion-composition __remotion-composition-selector-item ${hoverable_1.HOVERABLE_CLASS_NAME} ${hoverable_1.HOVER_GROUP_CLASS_NAME}`, "data-compname": item.composition.id, children: [
255
- jsx_runtime_1.jsx(CompositionOrStillIcon_1.CompositionOrStillIcon, { composition: item.composition, color: colors_1.CURRENT_COLOR, style: iconStyle }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 1 }), jsx_runtime_1.jsx("div", { style: labelStyle, children: item.composition.id }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(CompositionContextButton_1.CompositionContextButton, { getItems: getContextMenuItems, visible: !isDragging, readOnlyStudio: window.remotion_isReadOnlyStudio }), jsx_runtime_1.jsx(SidebarRenderButton_1.SidebarRenderButton, { visible: !isDragging, composition: item.composition, readOnlyStudio: window.remotion_isReadOnlyStudio })
256
- ] }) }) }));
524
+ return (jsx_runtime_1.jsx(ContextMenu_1.ContextMenu, { getItems: getContextMenuItems, children: jsx_runtime_1.jsxs("div", { style: reorderWrapper, children: [reorderLineStyle ? (jsx_runtime_1.jsx("div", { "data-composition-reorder-line": true, style: reorderLineStyle })) : null, jsx_runtime_1.jsx(layout_1.Row, { align: "center", children: jsx_runtime_1.jsxs("a", { ref: compositionRowRef, style: style, tabIndex: tabIndex, onClick: onClick, onKeyDown: onKeyDown, draggable: !window.remotion_isReadOnlyStudio, onDragStart: onItemDragStart, onDragEnd: onItemDragEnd, onDragOver: onRowDragOver, onDragLeave: onRowDragLeave, onDrop: onRowDrop, type: "button", title: item.composition.id, className: `__remotion-composition __remotion-composition-selector-item ${hoverable_1.HOVERABLE_CLASS_NAME} ${hoverable_1.HOVER_GROUP_CLASS_NAME}`, "data-compname": item.composition.id, children: [
525
+ jsx_runtime_1.jsx(CompositionOrStillIcon_1.CompositionOrStillIcon, { composition: item.composition, color: colors_1.CURRENT_COLOR, style: iconStyle }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 1 }), jsx_runtime_1.jsx("div", { style: labelStyle, children: item.composition.id }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(CompositionContextButton_1.CompositionContextButton, { getItems: getContextMenuItems, visible: !isDragging, readOnlyStudio: window.remotion_isReadOnlyStudio }), jsx_runtime_1.jsx(SidebarRenderButton_1.SidebarRenderButton, { visible: !isDragging, composition: item.composition, readOnlyStudio: window.remotion_isReadOnlyStudio })
526
+ ] }) })
527
+ ] }) }));
257
528
  };
258
529
  exports.CompositionSelectorItem = CompositionSelectorItem;
@@ -4,10 +4,12 @@ exports.TitleUpdater = void 0;
4
4
  const react_1 = require("react");
5
5
  const remotion_1 = require("remotion");
6
6
  const document_title_1 = require("../helpers/document-title");
7
+ const modals_1 = require("../state/modals");
7
8
  const context_1 = require("./RenderQueue/context");
8
9
  const TitleUpdater = () => {
9
10
  const renderQueue = (0, react_1.useContext)(context_1.RenderQueueContext);
10
11
  const { canvasContent } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
12
+ const selectedModal = (0, react_1.useContext)(modals_1.SelectedModalContext);
11
13
  const { jobs } = renderQueue;
12
14
  (0, react_1.useEffect)(() => {
13
15
  if (!canvasContent) {
@@ -31,6 +33,9 @@ const TitleUpdater = () => {
31
33
  (0, react_1.useEffect)(() => {
32
34
  (0, document_title_1.setRenderJobs)(jobs);
33
35
  }, [jobs]);
36
+ (0, react_1.useEffect)(() => {
37
+ (0, document_title_1.setCurrentModal)(selectedModal);
38
+ }, [selectedModal]);
34
39
  return null;
35
40
  };
36
41
  exports.TitleUpdater = TitleUpdater;
@@ -1,31 +1,10 @@
1
- import type { ElementInstallExpectedFileState, ElementInstallRequest } from '@remotion/studio-shared';
2
1
  import React from 'react';
2
+ import type { ElementInstallModalState } from '../state/modals';
3
3
  export declare const ElementLibraryAddConfirmation: React.FC<{
4
4
  readonly displayName: string | null;
5
5
  readonly origin: string;
6
6
  readonly url: string;
7
7
  }>;
8
- type ElementInstallPlan = {
9
- readonly compositionFile: string;
10
- readonly filePath: string;
11
- readonly expectedFileState: ElementInstallExpectedFileState;
12
- };
13
- type CurrentCompositionMetadata = {
14
- readonly durationInFrames: number;
15
- readonly fps: number;
16
- readonly height: number;
17
- readonly width: number;
18
- };
19
8
  export declare const ElementInstallConfirmation: React.FC<{
20
- readonly currentCompositionMetadata: CurrentCompositionMetadata | null;
21
- readonly currentPlan: ElementInstallPlan | null;
22
- readonly dependenciesToReview: string[];
23
- readonly missingPackages: string[];
24
- readonly newPlan: ElementInstallPlan;
25
- readonly onClose: () => void;
26
- readonly request: ElementInstallRequest;
27
- readonly sourceIsUnverified: boolean;
28
- readonly sourceLabel: string;
29
- readonly usesBrowserDependencyResolution: boolean;
9
+ readonly state: ElementInstallModalState;
30
10
  }>;
31
- export {};