@remotion/studio 4.0.513 → 4.0.515

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 (204) hide show
  1. package/dist/Studio.js +2 -1
  2. package/dist/api/install-package.js +14 -1
  3. package/dist/components/AskAiModal.js +1 -1
  4. package/dist/components/AssetSelector.js +2 -0
  5. package/dist/components/AssetSelectorItem.d.ts +2 -1
  6. package/dist/components/AssetSelectorItem.js +19 -16
  7. package/dist/components/AudioWaveform.d.ts +3 -0
  8. package/dist/components/AudioWaveform.js +65 -199
  9. package/dist/components/Canvas.js +40 -5
  10. package/dist/components/CanvasOrLoading.js +5 -0
  11. package/dist/components/CompositionSelector.js +2 -0
  12. package/dist/components/ConfigureDefaultEditorModal.js +17 -11
  13. package/dist/components/Editor.js +16 -1
  14. package/dist/components/ElementInstallConfirmation.d.ts +1 -0
  15. package/dist/components/ElementInstallConfirmation.js +4 -2
  16. package/dist/components/FixComputedValueModal.d.ts +9 -0
  17. package/dist/components/FixComputedValueModal.js +217 -0
  18. package/dist/components/InitialCompositionLoader.js +19 -0
  19. package/dist/components/InlineDropdown.js +4 -4
  20. package/dist/components/InspectorInfoHeader.js +3 -3
  21. package/dist/components/InspectorOpenInEditor.js +3 -1
  22. package/dist/components/InspectorPanel/CompositionInspector.js +37 -5
  23. package/dist/components/InspectorPanel/CompositionInspectorHeader.js +2 -2
  24. package/dist/components/InspectorPanel/ConnectedCompositionsSection.js +1 -1
  25. package/dist/components/InspectorPanel/EasingInspector.js +1 -1
  26. package/dist/components/InspectorPanel/KeyframeInspector.js +2 -2
  27. package/dist/components/InspectorPanel/SequenceInspectorHeader.js +1 -1
  28. package/dist/components/InspectorPanel/SequenceSelectionInspector.js +35 -6
  29. package/dist/components/InspectorPanel/common.d.ts +5 -5
  30. package/dist/components/InspectorPanel/common.js +8 -8
  31. package/dist/components/InspectorPanel/styles.d.ts +1 -1
  32. package/dist/components/InspectorPanel/styles.js +4 -2
  33. package/dist/components/InspectorSourceLocation.d.ts +1 -1
  34. package/dist/components/InspectorSourceLocation.js +2 -2
  35. package/dist/components/InstallPackage.d.ts +1 -1
  36. package/dist/components/InstallPackage.js +38 -6
  37. package/dist/components/LicenseKeyValidation.js +2 -2
  38. package/dist/components/Menu/MenuDivider.js +1 -1
  39. package/dist/components/Modals.js +11 -3
  40. package/dist/components/NewComposition/CodemodFooter.d.ts +1 -0
  41. package/dist/components/NewComposition/CodemodFooter.js +10 -8
  42. package/dist/components/NewComposition/DeleteComposition.js +1 -1
  43. package/dist/components/NewComposition/DeleteFolder.js +1 -1
  44. package/dist/components/NewComposition/DuplicateComposition.js +7 -2
  45. package/dist/components/NewComposition/NewComposition.js +1 -1
  46. package/dist/components/NewComposition/NewFolder.js +1 -1
  47. package/dist/components/NewComposition/RenameComposition.js +1 -1
  48. package/dist/components/NewComposition/RenameFolder.js +1 -1
  49. package/dist/components/NewComposition/duplicate-composition-api.d.ts +16 -0
  50. package/dist/components/NewComposition/duplicate-composition-api.js +16 -0
  51. package/dist/components/NoRegisterRoot.js +1 -1
  52. package/dist/components/QuickSwitcher/ExplorerQuickSwitcherTrigger.js +4 -3
  53. package/dist/components/QuickSwitcher/QuickSwitcherContent.js +1 -0
  54. package/dist/components/QuickSwitcher/fuzzy-search.js +1 -1
  55. package/dist/components/RefreshCompositionOverlay.js +1 -1
  56. package/dist/components/RenderButton.js +6 -3
  57. package/dist/components/RenderModal/GuiRenderStatus.js +3 -1
  58. package/dist/components/RenderModal/RenderModalOutputName.js +3 -3
  59. package/dist/components/RenderModal/WebRenderModal.js +10 -4
  60. package/dist/components/RenderModal/WebRenderModalAdvanced.d.ts +2 -0
  61. package/dist/components/RenderModal/WebRenderModalAdvanced.js +9 -2
  62. package/dist/components/RenderModal/render-modals.js +5 -1
  63. package/dist/components/RenderQueue/ClientRenderQueueProcessor.js +5 -1
  64. package/dist/components/RenderQueue/RenderQueueItem.js +3 -1
  65. package/dist/components/RenderQueue/RenderQueueOpenInFolder.js +3 -1
  66. package/dist/components/RenderQueue/RenderQueueRemoveItem.js +1 -1
  67. package/dist/components/RenderQueue/actions.js +12 -2
  68. package/dist/components/RenderQueue/client-side-render-types.d.ts +1 -0
  69. package/dist/components/RenderingSettings.d.ts +2 -0
  70. package/dist/components/RenderingSettings.js +355 -0
  71. package/dist/components/SelectedOutlineCanvasRotation.d.ts +1 -0
  72. package/dist/components/SelectedOutlineCanvasRotation.js +11 -4
  73. package/dist/components/SelectedOutlineElement.js +3 -3
  74. package/dist/components/SelectedOutlinePolygon.d.ts +2 -0
  75. package/dist/components/SelectedOutlinePolygon.js +54 -9
  76. package/dist/components/SettingsContext.d.ts +4 -1
  77. package/dist/components/SettingsContext.js +9 -2
  78. package/dist/components/SettingsModal.d.ts +1 -1
  79. package/dist/components/SettingsModal.js +10 -1
  80. package/dist/components/SettingsModalFooter.js +1 -1
  81. package/dist/components/StudioSettings.d.ts +2 -0
  82. package/dist/components/StudioSettings.js +185 -0
  83. package/dist/components/Timeline/LoopedIndicator.js +1 -1
  84. package/dist/components/Timeline/LoopedTimelineIndicators.d.ts +3 -0
  85. package/dist/components/Timeline/LoopedTimelineIndicators.js +22 -14
  86. package/dist/components/Timeline/Timeline.js +11 -9
  87. package/dist/components/Timeline/TimelineAssetField.d.ts +2 -2
  88. package/dist/components/Timeline/TimelineAssetField.js +1 -1
  89. package/dist/components/Timeline/TimelineClipboardKeybindings.js +6 -2
  90. package/dist/components/Timeline/TimelineDragHandler.js +62 -76
  91. package/dist/components/Timeline/TimelineEffectItem.js +23 -6
  92. package/dist/components/Timeline/TimelineEffectPropItem.d.ts +4 -2
  93. package/dist/components/Timeline/TimelineEffectPropItem.js +22 -13
  94. package/dist/components/Timeline/TimelineExpandArrowButton.js +10 -7
  95. package/dist/components/Timeline/TimelineExpandedKeyframeRow.js +4 -1
  96. package/dist/components/Timeline/TimelineExpandedRow.d.ts +1 -1
  97. package/dist/components/Timeline/TimelineExpandedRow.js +4 -4
  98. package/dist/components/Timeline/TimelineExpandedSection.js +8 -5
  99. package/dist/components/Timeline/TimelineHeightContainer.d.ts +0 -4
  100. package/dist/components/Timeline/TimelineHeightContainer.js +4 -4
  101. package/dist/components/Timeline/TimelineImageInfo.d.ts +1 -0
  102. package/dist/components/Timeline/TimelineImageInfo.js +3 -2
  103. package/dist/components/Timeline/TimelineKeyframeControls.js +6 -1
  104. package/dist/components/Timeline/TimelineList.d.ts +1 -5
  105. package/dist/components/Timeline/TimelineList.js +14 -9
  106. package/dist/components/Timeline/TimelinePinchZoom.js +5 -5
  107. package/dist/components/Timeline/TimelineRowChrome.d.ts +1 -2
  108. package/dist/components/Timeline/TimelineRowChrome.js +50 -7
  109. package/dist/components/Timeline/TimelineSchemaField.d.ts +7 -3
  110. package/dist/components/Timeline/TimelineSchemaField.js +71 -13
  111. package/dist/components/Timeline/TimelineScrollable.js +3 -1
  112. package/dist/components/Timeline/TimelineSelection.d.ts +13 -5
  113. package/dist/components/Timeline/TimelineSelection.js +95 -106
  114. package/dist/components/Timeline/TimelineSequence.js +59 -25
  115. package/dist/components/Timeline/TimelineSequenceItem.d.ts +1 -1
  116. package/dist/components/Timeline/TimelineSequenceItem.js +21 -12
  117. package/dist/components/Timeline/TimelineSequenceName.js +1 -1
  118. package/dist/components/Timeline/TimelineSequencePropItem.d.ts +2 -1
  119. package/dist/components/Timeline/TimelineSequencePropItem.js +3 -3
  120. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +33 -10
  121. package/dist/components/Timeline/TimelineSlider.js +42 -33
  122. package/dist/components/Timeline/TimelineTimeIndicators.js +90 -98
  123. package/dist/components/Timeline/TimelineTrack.js +4 -1
  124. package/dist/components/Timeline/TimelineTracks.d.ts +0 -2
  125. package/dist/components/Timeline/TimelineTracks.js +11 -4
  126. package/dist/components/Timeline/TimelineTransformOriginField.js +1 -1
  127. package/dist/components/Timeline/TimelineVideoInfo.d.ts +4 -4
  128. package/dist/components/Timeline/TimelineVideoInfo.js +155 -63
  129. package/dist/components/Timeline/TimelineViewport.d.ts +12 -0
  130. package/dist/components/Timeline/TimelineViewport.js +62 -0
  131. package/dist/components/Timeline/TimelineVirtualization.d.ts +22 -0
  132. package/dist/components/Timeline/TimelineVirtualization.js +144 -0
  133. package/dist/components/Timeline/TimelineZoomControls.js +16 -8
  134. package/dist/components/Timeline/call-add-keyframe.js +31 -3
  135. package/dist/components/Timeline/call-delete-keyframe.js +13 -3
  136. package/dist/components/Timeline/call-move-keyframe.js +11 -1
  137. package/dist/components/Timeline/call-update-keyframe-settings.js +31 -3
  138. package/dist/components/Timeline/delete-selected-timeline-item.js +8 -3
  139. package/dist/components/Timeline/duplicate-selected-timeline-item.js +4 -2
  140. package/dist/components/Timeline/get-timeline-keyframes.d.ts +1 -2
  141. package/dist/components/Timeline/get-timeline-keyframes.js +1 -8
  142. package/dist/components/Timeline/get-timeline-sequence-visible-layout.d.ts +30 -0
  143. package/dist/components/Timeline/get-timeline-sequence-visible-layout.js +61 -0
  144. package/dist/components/Timeline/save-effect-prop.js +3 -3
  145. package/dist/components/Timeline/split-selected-timeline-item.js +2 -2
  146. package/dist/components/Timeline/timeline-scroll-logic.d.ts +24 -0
  147. package/dist/components/Timeline/timeline-scroll-logic.js +127 -4
  148. package/dist/components/Timeline/use-timeline-height.d.ts +3 -5
  149. package/dist/components/Timeline/use-timeline-height.js +16 -18
  150. package/dist/components/UpdateCheck.d.ts +2 -10
  151. package/dist/components/UpdateCheck.js +8 -2
  152. package/dist/components/VisualControls/VisualControlHandle.js +8 -0
  153. package/dist/components/delete-jsx-node-api.d.ts +2 -0
  154. package/dist/components/delete-jsx-node-api.js +12 -0
  155. package/dist/components/effect-drag-and-drop.js +6 -3
  156. package/dist/components/effect-operations-api.d.ts +8 -0
  157. package/dist/components/effect-operations-api.js +52 -0
  158. package/dist/components/element-install-api.d.ts +3 -0
  159. package/dist/components/element-install-api.js +19 -0
  160. package/dist/components/import-assets.js +20 -9
  161. package/dist/components/reorder-sequence-api.d.ts +2 -0
  162. package/dist/components/reorder-sequence-api.js +12 -0
  163. package/dist/components/split-jsx-sequence-api.d.ts +2 -0
  164. package/dist/components/split-jsx-sequence-api.js +12 -0
  165. package/dist/components/split-video-from-audio-api.d.ts +2 -0
  166. package/dist/components/split-video-from-audio-api.js +12 -0
  167. package/dist/error-overlay/remotion-overlay/Overlay.js +1 -1
  168. package/dist/error-overlay/remotion-overlay/log-studio-error.js +4 -0
  169. package/dist/esm/{chunk-r46yxrjr.js → chunk-s6k99gh2.js} +1 -1
  170. package/dist/esm/{chunk-tv7r0jy3.js → chunk-v5a8vpv4.js} +11479 -7851
  171. package/dist/esm/index.mjs +7 -5
  172. package/dist/esm/internals.mjs +11479 -7851
  173. package/dist/esm/previewEntry.mjs +11311 -7683
  174. package/dist/esm/renderEntry.mjs +3 -4
  175. package/dist/helpers/browser-studio-operations.d.ts +5 -0
  176. package/dist/helpers/browser-studio-operations.js +27 -1
  177. package/dist/helpers/colors.d.ts +1 -1
  178. package/dist/helpers/colors.js +1 -1
  179. package/dist/helpers/get-timeline-max-zoom.d.ts +26 -0
  180. package/dist/helpers/get-timeline-max-zoom.js +45 -0
  181. package/dist/helpers/inject-css.js +7 -5
  182. package/dist/helpers/render-codec-label.d.ts +1 -1
  183. package/dist/helpers/retry-payload.js +1 -0
  184. package/dist/helpers/studio-runtime-config.d.ts +1 -1
  185. package/dist/helpers/studio-runtime-config.js +2 -3
  186. package/dist/helpers/timeline-layout.d.ts +3 -1
  187. package/dist/helpers/timeline-layout.js +6 -1
  188. package/dist/helpers/url-state.js +3 -2
  189. package/dist/helpers/use-max-media-duration.js +5 -3
  190. package/dist/helpers/use-media-metadata.js +37 -20
  191. package/dist/helpers/use-menu-structure.js +67 -84
  192. package/dist/helpers/use-runtime-values.d.ts +2 -1
  193. package/dist/helpers/use-runtime-values.js +7 -3
  194. package/dist/icons/cloud-download.d.ts +4 -0
  195. package/dist/icons/cloud-download.js +8 -0
  196. package/dist/icons/remotion-triangle.d.ts +2 -0
  197. package/dist/icons/remotion-triangle.js +7 -0
  198. package/dist/renderEntry.js +1 -1
  199. package/dist/state/composition-list.d.ts +13 -0
  200. package/dist/state/composition-list.js +21 -0
  201. package/dist/state/modals.d.ts +8 -2
  202. package/dist/state/timeline-zoom.d.ts +1 -2
  203. package/dist/state/timeline-zoom.js +9 -5
  204. package/package.json +14 -13
package/dist/Studio.js CHANGED
@@ -12,13 +12,14 @@ const use_static_files_1 = require("./components/use-static-files");
12
12
  const FastRefreshProvider_1 = require("./FastRefreshProvider");
13
13
  const inject_css_1 = require("./helpers/inject-css");
14
14
  const ResolveCompositionConfigInStudio_1 = require("./ResolveCompositionConfigInStudio");
15
+ const composition_list_1 = require("./state/composition-list");
15
16
  const getServerDisconnectedDomElement = () => {
16
17
  return document.getElementById('server-disconnected-overlay');
17
18
  };
18
19
  const StudioInner = ({ rootComponent, readOnly }) => {
19
20
  var _a, _b, _c;
20
21
  return (jsx_runtime_1.jsx(remotion_1.Internals.CompositionManagerProvider, { onlyRenderComposition: null, currentCompositionMetadata: null, initialCompositions: [], initialCanvasContent: null, children: jsx_runtime_1.jsx(remotion_1.Internals.RemotionRootContexts, { frameState: null, audioEnabled: window.remotion_audioEnabled, videoEnabled: window.remotion_videoEnabled, logLevel: (_a = window.remotion_logLevel) !== null && _a !== void 0 ? _a : 'info', numberOfAudioTags: window.remotion_numberOfAudioTags, audioLatencyHint: (_b = window.remotion_audioLatencyHint) !== null && _b !== void 0 ? _b : 'playback', previewSampleRate: window.remotion_previewSampleRate, _experimentalKeepAudioContextAlive: (_c = window.remotion_experimentalKeepAudioContextAlive) !== null && _c !== void 0 ? _c : false, children: jsx_runtime_1.jsx(use_static_files_1.StaticFilesProvider, { children: jsx_runtime_1.jsx(ResolveCompositionConfigInStudio_1.ResolveCompositionConfigInStudio, { children: jsx_runtime_1.jsxs(EditorContexts_1.EditorContexts, { children: [
21
- jsx_runtime_1.jsx(Editor_1.Editor, { readOnlyStudio: readOnly, Root: rootComponent }), readOnly
22
+ jsx_runtime_1.jsx(composition_list_1.CompositionListProvider, { children: jsx_runtime_1.jsx(Editor_1.Editor, { readOnlyStudio: readOnly, Root: rootComponent }) }), readOnly
22
23
  ? null
23
24
  : (0, react_dom_1.createPortal)(jsx_runtime_1.jsx(ServerDisconnected_1.ServerDisconnected, {}), getServerDisconnectedDomElement())] }) }) }) }) }));
24
25
  };
@@ -3,10 +3,23 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.installPackages = void 0;
4
4
  const remotion_1 = require("remotion");
5
5
  const call_api_1 = require("../components/call-api");
6
- const installPackages = (dependencies) => {
6
+ const browser_studio_operations_1 = require("../helpers/browser-studio-operations");
7
+ const installPackages = async (dependencies) => {
7
8
  if (!(0, remotion_1.getRemotionEnvironment)().isStudio) {
8
9
  throw new Error('installPackages() is only available in the Studio');
9
10
  }
11
+ const browserStudioOperations = (0, browser_studio_operations_1.getBrowserStudioOperations)();
12
+ if (browserStudioOperations !== null) {
13
+ const response = await browserStudioOperations.packageInstallation.installPackages({
14
+ dependencies: [...dependencies],
15
+ });
16
+ if (!response.success) {
17
+ const error = new Error(response.reason);
18
+ error.stack = response.stack;
19
+ throw error;
20
+ }
21
+ return {};
22
+ }
10
23
  if (window.remotion_isReadOnlyStudio) {
11
24
  throw new Error('installPackages() is not available in Read-Only Studio');
12
25
  }
@@ -63,7 +63,7 @@ const AskAiModal = () => {
63
63
  if (state === 'never-opened') {
64
64
  return null;
65
65
  }
66
- return (jsx_runtime_1.jsx(remotion_1.AbsoluteFill, { style: { display: state === 'visible' ? 'block' : 'none' }, children: jsx_runtime_1.jsxs(ModalContainer_1.ModalContainer, { noZIndex: state === 'hidden', onOutsideClick: onQuit, onEscape: onQuit, children: [
66
+ return (jsx_runtime_1.jsx(remotion_1.Internals.AbsoluteFillElement, { style: { display: state === 'visible' ? 'block' : 'none' }, children: jsx_runtime_1.jsxs(ModalContainer_1.ModalContainer, { noZIndex: state === 'hidden', onOutsideClick: onQuit, onEscape: onQuit, children: [
67
67
  jsx_runtime_1.jsx(ModalHeader_1.ModalHeader, { title: "Ask AI", onClose: onQuit }), jsx_runtime_1.jsx("iframe", { ref: iframe, frameBorder: 0, style: container, src: "https://www.remotion.dev/ai-embed", allow: "clipboard-read; clipboard-write" })
68
68
  ] }) }));
69
69
  };
@@ -75,6 +75,8 @@ const label = {
75
75
  };
76
76
  const baseList = {
77
77
  overflowY: 'auto',
78
+ paddingTop: 4,
79
+ paddingBottom: 4,
78
80
  };
79
81
  const AssetSelector = ({ readOnlyStudio }) => {
80
82
  const { tabIndex } = (0, z_index_1.useZIndex)();
@@ -14,7 +14,7 @@ export declare const getCanDragAsset: ({ readOnlyStudio, relativePath, }: {
14
14
  readOnlyStudio: boolean;
15
15
  relativePath: string;
16
16
  }) => boolean;
17
- export declare const getAssetContextMenuItems: ({ relativePath, fileManagerName, copyFileName, copyStaticFilePath, openAssetInExplorer, renameAsset, deleteAsset, fileExplorerDisabled, mutationsDisabled, }: {
17
+ export declare const getAssetContextMenuItems: ({ relativePath, fileManagerName, copyFileName, copyStaticFilePath, openAssetInExplorer, renameAsset, deleteAsset, fileExplorerAvailable, fileExplorerDisabled, mutationsDisabled, }: {
18
18
  relativePath: string;
19
19
  fileManagerName: string;
20
20
  copyFileName: () => void;
@@ -22,6 +22,7 @@ export declare const getAssetContextMenuItems: ({ relativePath, fileManagerName,
22
22
  openAssetInExplorer: () => void;
23
23
  renameAsset: () => void;
24
24
  deleteAsset: () => void;
25
+ fileExplorerAvailable: boolean;
25
26
  fileExplorerDisabled: boolean;
26
27
  mutationsDisabled: boolean;
27
28
  }) => ComboboxValue[];
@@ -80,11 +80,10 @@ const itemStyle = {
80
80
  alignItems: 'center',
81
81
  marginBottom: 1,
82
82
  marginLeft: 4,
83
- marginRight: 4,
84
83
  appearance: 'none',
85
84
  border: 'none',
86
85
  borderRadius: 4,
87
- width: 'calc(100% - 8px)',
86
+ width: 'calc(100% - 4px)',
88
87
  textAlign: 'left',
89
88
  backgroundColor: colors_1.BACKGROUND,
90
89
  height: layout_1.COMPACT_CONTROL_ROW_HEIGHT,
@@ -118,8 +117,8 @@ const getCanDragAsset = ({ readOnlyStudio, relativePath, }) => {
118
117
  return !readOnlyStudio && (0, import_assets_1.getAssetElementFromPath)(relativePath) !== null;
119
118
  };
120
119
  exports.getCanDragAsset = getCanDragAsset;
121
- const getAssetContextMenuItems = ({ relativePath, fileManagerName, copyFileName, copyStaticFilePath, openAssetInExplorer, renameAsset, deleteAsset, fileExplorerDisabled, mutationsDisabled, }) => {
122
- return [
120
+ const getAssetContextMenuItems = ({ relativePath, fileManagerName, copyFileName, copyStaticFilePath, openAssetInExplorer, renameAsset, deleteAsset, fileExplorerAvailable, fileExplorerDisabled, mutationsDisabled, }) => {
121
+ const items = [
123
122
  (0, open_in_new_window_1.getOpenInNewWindowMenuItem)(`/assets/${relativePath}`),
124
123
  {
125
124
  type: 'divider',
@@ -151,18 +150,20 @@ const getAssetContextMenuItems = ({ relativePath, fileManagerName, copyFileName,
151
150
  type: 'divider',
152
151
  id: 'asset-file-actions-divider',
153
152
  },
154
- {
155
- id: 'open-asset-in-explorer',
156
- keyHint: null,
157
- label: `Show in ${fileManagerName}`,
158
- leftItem: null,
159
- onClick: openAssetInExplorer,
160
- quickSwitcherLabel: `Show asset in ${fileManagerName}`,
161
- subMenu: null,
162
- type: 'item',
163
- value: 'open-asset-in-explorer',
164
- disabled: fileExplorerDisabled,
165
- },
153
+ fileExplorerAvailable
154
+ ? {
155
+ id: 'open-asset-in-explorer',
156
+ keyHint: null,
157
+ label: `Show in ${fileManagerName}`,
158
+ leftItem: null,
159
+ onClick: openAssetInExplorer,
160
+ quickSwitcherLabel: `Show asset in ${fileManagerName}`,
161
+ subMenu: null,
162
+ type: 'item',
163
+ value: 'open-asset-in-explorer',
164
+ disabled: fileExplorerDisabled,
165
+ }
166
+ : null,
166
167
  {
167
168
  id: 'rename-asset',
168
169
  keyHint: null,
@@ -188,6 +189,7 @@ const getAssetContextMenuItems = ({ relativePath, fileManagerName, copyFileName,
188
189
  disabled: mutationsDisabled,
189
190
  },
190
191
  ];
192
+ return items.filter(no_react_1.NoReactInternals.truthy);
191
193
  };
192
194
  exports.getAssetContextMenuItems = getAssetContextMenuItems;
193
195
  const AssetFolderItem = ({ tabIndex, item, level, parentFolder, toggleFolder, dropLocation, setDropLocation, readOnlyStudio, }) => {
@@ -433,6 +435,7 @@ const AssetSelectorItem = ({ item, tabIndex, level, parentFolder, readOnlyStudio
433
435
  openAssetInExplorer,
434
436
  renameAsset,
435
437
  deleteAsset,
438
+ fileExplorerAvailable: (0, browser_studio_operations_1.getBrowserStudioOperations)() === null,
436
439
  fileExplorerDisabled,
437
440
  mutationsDisabled,
438
441
  });
@@ -6,8 +6,11 @@ export declare const AudioWaveform: React.NamedExoticComponent<{
6
6
  readonly visualizationWidth: number;
7
7
  readonly startFrom: number;
8
8
  readonly durationInFrames: number;
9
+ readonly displayOffsetInFrames: number;
10
+ readonly displayDurationInFrames: number;
9
11
  readonly volume: string | number;
10
12
  readonly doesVolumeChange: boolean;
13
+ readonly muted: boolean;
11
14
  readonly playbackRate: number;
12
15
  readonly loopDisplay: LoopDisplay | undefined;
13
16
  }>;
@@ -41,19 +41,6 @@ const remotion_1 = require("remotion");
41
41
  const colors_1 = require("../helpers/colors");
42
42
  const timeline_layout_1 = require("../helpers/timeline-layout");
43
43
  const EMPTY_PEAKS = new Float32Array(0);
44
- // Recreate the canvas after Fast Refresh because an already transferred canvas
45
- // cannot be handed to OffscreenCanvas again.
46
- const canRetryCanvasTransfer = (err) => {
47
- return err instanceof DOMException && err.name === 'InvalidStateError';
48
- };
49
- const canUseAudioWaveformWorker = () => {
50
- if (typeof Worker === 'undefined' ||
51
- typeof OffscreenCanvas === 'undefined' ||
52
- typeof HTMLCanvasElement === 'undefined') {
53
- return false;
54
- }
55
- return 'transferControlToOffscreen' in HTMLCanvasElement.prototype;
56
- };
57
44
  const getContainerStyle = (height) => {
58
45
  return {
59
46
  display: 'flex',
@@ -64,9 +51,6 @@ const getContainerStyle = (height) => {
64
51
  height,
65
52
  };
66
53
  };
67
- const getWaveformErrorMessage = () => {
68
- return new Error('No waveform available. The audio could not be decoded or may not support CORS.');
69
- };
70
54
  const waveformCanvasStyle = {
71
55
  pointerEvents: 'none',
72
56
  width: '100%',
@@ -74,6 +58,8 @@ const waveformCanvasStyle = {
74
58
  };
75
59
  const volumeCanvasStyle = {
76
60
  position: 'absolute',
61
+ width: '100%',
62
+ height: '100%',
77
63
  };
78
64
  const parseVolume = (volume) => {
79
65
  if (typeof volume === 'number') {
@@ -81,139 +67,62 @@ const parseVolume = (volume) => {
81
67
  }
82
68
  return volume.split(',').map((v) => Number(v));
83
69
  };
84
- const drawLoopedWaveform = ({ canvas, peaks, volume, visualizationWidth, loopWidth, }) => {
85
- const h = canvas.height;
86
- const w = Math.ceil(visualizationWidth);
87
- const targetCanvas = document.createElement('canvas');
88
- targetCanvas.width = Math.max(1, Math.ceil(loopWidth));
89
- targetCanvas.height = h;
90
- (0, timeline_utils_1.drawBars)({
91
- canvas: targetCanvas,
92
- peaks,
93
- color: colors_1.WHITE_ALPHA_60,
94
- volume,
95
- width: targetCanvas.width,
96
- });
97
- canvas.width = w;
98
- canvas.height = h;
99
- const ctx = canvas.getContext('2d');
100
- if (!ctx) {
101
- throw new Error('Failed to get canvas context');
102
- }
103
- const pattern = ctx.createPattern(targetCanvas, 'repeat-x');
104
- if (!pattern) {
105
- return;
106
- }
107
- pattern.setTransform(new DOMMatrix().scaleSelf(loopWidth / targetCanvas.width, 1));
108
- ctx.clearRect(0, 0, w, h);
109
- ctx.fillStyle = pattern;
110
- ctx.fillRect(0, 0, w, h);
111
- };
112
- const AudioWaveformInner = ({ src, height, startFrom, durationInFrames, visualizationWidth, volume, doesVolumeChange, playbackRate, loopDisplay, }) => {
70
+ const AudioWaveformInner = ({ src, height, startFrom, durationInFrames, displayOffsetInFrames, displayDurationInFrames, visualizationWidth, volume, doesVolumeChange, muted, playbackRate, loopDisplay, }) => {
113
71
  const [peaks, setPeaks] = (0, react_1.useState)(null);
114
72
  const [error, setError] = (0, react_1.useState)(null);
115
- const [waveformCanvasKey, setWaveformCanvasKey] = (0, react_1.useState)(0);
116
- const canUseWorkerPath = (0, react_1.useMemo)(() => canUseAudioWaveformWorker(), []);
117
73
  const vidConf = remotion_1.Internals.useUnsafeVideoConfig();
118
74
  if (vidConf === null) {
119
75
  throw new Error('Expected video config');
120
76
  }
121
77
  const waveformCanvas = (0, react_1.useRef)(null);
122
78
  const volumeCanvas = (0, react_1.useRef)(null);
123
- const waveformWorker = (0, react_1.useRef)(null);
124
- const hasTransferredCanvas = (0, react_1.useRef)(false);
125
- const latestRequestId = (0, react_1.useRef)(0);
126
79
  const shouldRenderVolumeOverlay = doesVolumeChange && typeof volume === 'string';
127
80
  const parsedVolume = (0, react_1.useMemo)(() => parseVolume(volume), [volume]);
128
- (0, react_1.useEffect)(() => {
129
- if (canUseWorkerPath) {
130
- return;
81
+ const visibleVolume = (0, react_1.useMemo)(() => {
82
+ if (muted) {
83
+ return 0;
131
84
  }
132
- const controller = new AbortController();
85
+ return (0, timeline_utils_1.getVisibleWaveformVolume)({
86
+ displayDurationInFrames,
87
+ displayOffsetInFrames,
88
+ loopDisplay,
89
+ volume: parsedVolume,
90
+ });
91
+ }, [
92
+ displayDurationInFrames,
93
+ displayOffsetInFrames,
94
+ loopDisplay,
95
+ muted,
96
+ parsedVolume,
97
+ ]);
98
+ // Layout effect so that a cache hit sets the peaks synchronously and the
99
+ // waveform is painted on the very first frame after mounting.
100
+ (0, react_1.useLayoutEffect)(() => {
133
101
  setPeaks(null);
134
102
  setError(null);
135
- (0, timeline_utils_1.loadWaveformPeaks)(src, controller.signal)
136
- .then((p) => {
137
- if (!controller.signal.aborted) {
138
- setPeaks(p);
139
- }
140
- })
141
- .catch((err) => {
142
- if (!controller.signal.aborted) {
143
- setError(err);
144
- }
145
- });
146
- return () => controller.abort();
147
- }, [canUseWorkerPath, src]);
148
- (0, react_1.useEffect)(() => {
149
- if (!canUseWorkerPath) {
150
- return;
151
- }
152
- const canvasElement = waveformCanvas.current;
153
- if (!canvasElement || hasTransferredCanvas.current) {
154
- return;
155
- }
156
- const worker = (0, timeline_utils_1.makeAudioWaveformWorker)();
157
- let workerFailed = false;
158
- waveformWorker.current = worker;
159
- worker.addEventListener('message', (event) => {
160
- if (event.data.type === 'error') {
161
- if (event.data.requestId !== latestRequestId.current) {
162
- return;
163
- }
164
- setError(new Error(event.data.message));
165
- }
166
- });
167
- worker.addEventListener('error', (event) => {
168
- event.preventDefault();
169
- workerFailed = true;
170
- if (worker !== waveformWorker.current) {
171
- return;
172
- }
173
- worker.terminate();
174
- waveformWorker.current = null;
175
- hasTransferredCanvas.current = false;
176
- setError(getWaveformErrorMessage());
103
+ return (0, timeline_utils_1.subscribeToWaveformPeaks)({
104
+ src,
105
+ onPeaks: (p) => setPeaks(p),
106
+ onError: (err) => setError(err),
177
107
  });
178
- let offscreen;
179
- try {
180
- offscreen = canvasElement.transferControlToOffscreen();
181
- }
182
- catch (err) {
183
- worker.terminate();
184
- waveformWorker.current = null;
185
- if (canRetryCanvasTransfer(err)) {
186
- setWaveformCanvasKey((key) => key + 1);
187
- return;
188
- }
189
- throw err;
190
- }
191
- hasTransferredCanvas.current = true;
192
- worker.postMessage({ type: 'init', canvas: offscreen }, [offscreen]);
193
- return () => {
194
- if (!workerFailed) {
195
- worker.postMessage({ type: 'dispose' });
196
- }
197
- worker.terminate();
198
- waveformWorker.current = null;
199
- hasTransferredCanvas.current = false;
200
- };
201
- }, [canUseWorkerPath, waveformCanvasKey]);
108
+ }, [src]);
202
109
  const portionPeaks = (0, react_1.useMemo)(() => {
203
- if (canUseWorkerPath || !peaks) {
110
+ if (!peaks) {
204
111
  return null;
205
112
  }
206
- return (0, timeline_utils_1.sliceWaveformPeaks)({
207
- durationInFrames: (0, timeline_utils_1.shouldTileLoopDisplay)(loopDisplay)
208
- ? loopDisplay.durationInFrames
209
- : durationInFrames,
113
+ return (0, timeline_utils_1.sliceVisibleWaveformPeaks)({
114
+ displayDurationInFrames,
115
+ displayOffsetInFrames,
116
+ durationInFrames,
210
117
  fps: vidConf.fps,
118
+ loopDisplay,
211
119
  peaks,
212
120
  playbackRate,
213
121
  startFrom,
214
122
  });
215
123
  }, [
216
- canUseWorkerPath,
124
+ displayDurationInFrames,
125
+ displayOffsetInFrames,
217
126
  durationInFrames,
218
127
  loopDisplay,
219
128
  peaks,
@@ -221,74 +130,28 @@ const AudioWaveformInner = ({ src, height, startFrom, durationInFrames, visualiz
221
130
  startFrom,
222
131
  vidConf.fps,
223
132
  ]);
224
- (0, react_1.useEffect)(() => {
133
+ // Drawing must happen in a layout effect: when the timeline zooms, the
134
+ // canvas CSS box resizes in the same commit, and painting the bitmap
135
+ // before the browser paints avoids showing a stretched stale waveform.
136
+ (0, react_1.useLayoutEffect)(() => {
225
137
  const { current: canvasElement } = waveformCanvas;
226
138
  if (!canvasElement) {
227
139
  return;
228
140
  }
229
- const h = height;
230
- const w = Math.ceil(visualizationWidth);
231
- if (canUseWorkerPath) {
232
- const worker = waveformWorker.current;
233
- if (!worker || !hasTransferredCanvas.current) {
234
- return;
235
- }
236
- latestRequestId.current += 1;
237
- setError(null);
238
- const message = {
239
- type: 'render',
240
- requestId: latestRequestId.current,
241
- src,
242
- width: w,
243
- height: h,
244
- volume: parsedVolume,
245
- startFrom,
246
- durationInFrames,
247
- fps: vidConf.fps,
248
- playbackRate,
249
- loopDisplay,
250
- };
251
- worker.postMessage(message);
252
- return;
253
- }
141
+ const pixelRatio = window.devicePixelRatio;
142
+ const h = Math.ceil(height * pixelRatio);
143
+ const w = Math.ceil(visualizationWidth * pixelRatio);
254
144
  canvasElement.width = w;
255
145
  canvasElement.height = h;
256
- if ((0, timeline_utils_1.shouldTileLoopDisplay)(loopDisplay)) {
257
- drawLoopedWaveform({
258
- canvas: canvasElement,
259
- peaks: portionPeaks !== null && portionPeaks !== void 0 ? portionPeaks : EMPTY_PEAKS,
260
- volume: parsedVolume,
261
- visualizationWidth,
262
- loopWidth: (0, timeline_utils_1.getLoopDisplayWidth)({
263
- visualizationWidth,
264
- loopDisplay,
265
- }),
266
- });
267
- }
268
- else {
269
- (0, timeline_utils_1.drawBars)({
270
- canvas: canvasElement,
271
- peaks: portionPeaks !== null && portionPeaks !== void 0 ? portionPeaks : EMPTY_PEAKS,
272
- color: colors_1.WHITE_ALPHA_60,
273
- volume: parsedVolume,
274
- width: w,
275
- });
276
- }
277
- }, [
278
- canUseWorkerPath,
279
- durationInFrames,
280
- height,
281
- loopDisplay,
282
- playbackRate,
283
- parsedVolume,
284
- portionPeaks,
285
- src,
286
- startFrom,
287
- vidConf.fps,
288
- visualizationWidth,
289
- waveformCanvasKey,
290
- ]);
291
- (0, react_1.useEffect)(() => {
146
+ (0, timeline_utils_1.drawBars)({
147
+ canvas: canvasElement,
148
+ peaks: portionPeaks !== null && portionPeaks !== void 0 ? portionPeaks : EMPTY_PEAKS,
149
+ color: colors_1.WHITE_ALPHA_60,
150
+ volume: visibleVolume,
151
+ width: w,
152
+ });
153
+ }, [height, portionPeaks, visibleVolume, visualizationWidth]);
154
+ (0, react_1.useLayoutEffect)(() => {
292
155
  if (!shouldRenderVolumeOverlay) {
293
156
  return;
294
157
  }
@@ -296,24 +159,26 @@ const AudioWaveformInner = ({ src, height, startFrom, durationInFrames, visualiz
296
159
  if (!volumeCanvasElement) {
297
160
  return;
298
161
  }
299
- const h = height;
162
+ const pixelRatio = window.devicePixelRatio;
163
+ const h = Math.ceil(height * pixelRatio);
164
+ const w = Math.ceil(visualizationWidth * pixelRatio);
300
165
  const context = volumeCanvasElement.getContext('2d');
301
166
  if (!context) {
302
167
  return;
303
168
  }
304
- volumeCanvasElement.width = Math.ceil(visualizationWidth);
169
+ volumeCanvasElement.width = w;
305
170
  volumeCanvasElement.height = h;
306
- context.clearRect(0, 0, visualizationWidth, h);
307
- if (!Array.isArray(parsedVolume)) {
171
+ context.clearRect(0, 0, w, h);
172
+ if (!Array.isArray(visibleVolume)) {
308
173
  return;
309
174
  }
310
175
  context.beginPath();
311
176
  context.moveTo(0, h);
312
- parsedVolume.forEach((v, index) => {
313
- const x = parsedVolume.length <= 1
177
+ visibleVolume.forEach((v, index) => {
178
+ const x = visibleVolume.length <= 1
314
179
  ? 0
315
- : (index / (parsedVolume.length - 1)) * visualizationWidth;
316
- const y = (1 - v) * (h - timeline_layout_1.TIMELINE_BORDER * 2) + 1;
180
+ : (index / (visibleVolume.length - 1)) * w;
181
+ const y = (1 - v) * (h - timeline_layout_1.TIMELINE_BORDER * 2 * pixelRatio) + pixelRatio;
317
182
  if (index === 0) {
318
183
  context.moveTo(x, y);
319
184
  }
@@ -322,15 +187,16 @@ const AudioWaveformInner = ({ src, height, startFrom, durationInFrames, visualiz
322
187
  }
323
188
  });
324
189
  context.strokeStyle = colors_1.WHITE_ALPHA_70;
190
+ context.lineWidth = pixelRatio;
325
191
  context.stroke();
326
- }, [height, parsedVolume, shouldRenderVolumeOverlay, visualizationWidth]);
192
+ }, [height, shouldRenderVolumeOverlay, visibleVolume, visualizationWidth]);
327
193
  if (error) {
328
194
  return null;
329
195
  }
330
- if (!canUseWorkerPath && !peaks) {
196
+ if (!peaks) {
331
197
  return null;
332
198
  }
333
199
  return (jsx_runtime_1.jsxs("div", { style: getContainerStyle(height), children: [
334
- jsx_runtime_1.jsx("canvas", { ref: waveformCanvas, style: waveformCanvasStyle }, waveformCanvasKey), shouldRenderVolumeOverlay ? (jsx_runtime_1.jsx("canvas", { ref: volumeCanvas, style: volumeCanvasStyle })) : null] }));
200
+ jsx_runtime_1.jsx("canvas", { ref: waveformCanvas, style: waveformCanvasStyle }), shouldRenderVolumeOverlay ? (jsx_runtime_1.jsx("canvas", { ref: volumeCanvas, style: volumeCanvasStyle })) : null] }));
335
201
  };
336
202
  exports.AudioWaveform = react_1.default.memo(AudioWaveformInner);
@@ -9,6 +9,7 @@ const studio_protocol_1 = require("@remotion/studio-protocol");
9
9
  const react_1 = require("react");
10
10
  const remotion_1 = require("remotion");
11
11
  const get_static_files_1 = require("../api/get-static-files");
12
+ const browser_studio_operations_1 = require("../helpers/browser-studio-operations");
12
13
  const client_id_1 = require("../helpers/client-id");
13
14
  const clipboard_figma_1 = require("../helpers/clipboard-figma");
14
15
  const clipboard_images_1 = require("../helpers/clipboard-images");
@@ -35,6 +36,7 @@ const EditorGuides_1 = __importDefault(require("./EditorGuides"));
35
36
  const EditorRuler_1 = require("./EditorRuler");
36
37
  const use_is_ruler_visible_1 = require("./EditorRuler/use-is-ruler-visible");
37
38
  const effect_drag_and_drop_1 = require("./effect-drag-and-drop");
39
+ const element_install_api_1 = require("./element-install-api");
38
40
  const element_install_request_1 = require("./element-install-request");
39
41
  const ElementInstallConfirmation_1 = require("./ElementInstallConfirmation");
40
42
  const handle_drop_1 = require("./handle-drop");
@@ -618,6 +620,33 @@ const Canvas = ({ canvasContent, size }) => {
618
620
  setPendingElementInstallRequests((requests) => [...requests, request]);
619
621
  });
620
622
  }, []);
623
+ (0, react_1.useEffect)(() => {
624
+ var _a;
625
+ var _b;
626
+ if (!canInstallElements ||
627
+ compositionFile === null ||
628
+ currentCompositionId === null) {
629
+ return;
630
+ }
631
+ const initialElement = (_b = (_a = (0, browser_studio_operations_1.getBrowserStudioOperations)()) === null || _a === void 0 ? void 0 : _a.consumeInitialElement()) !== null && _b !== void 0 ? _b : null;
632
+ if (initialElement === null) {
633
+ return;
634
+ }
635
+ (0, element_install_request_1.enqueueElementInstallRequest)({
636
+ clientId: 'browser-studio',
637
+ compositionFile,
638
+ compositionId: currentCompositionId,
639
+ createdAt: Date.now(),
640
+ element: initialElement.element,
641
+ from: null,
642
+ id: crypto.randomUUID(),
643
+ position: null,
644
+ source: {
645
+ origin: initialElement.sourceOrigin,
646
+ type: 'browser-studio-link',
647
+ },
648
+ });
649
+ }, [canInstallElements, compositionFile, currentCompositionId]);
621
650
  (0, react_1.useEffect)(() => {
622
651
  if (activeElementInstallRequest !== null ||
623
652
  pendingElementInstallRequests.length === 0) {
@@ -636,8 +665,9 @@ const Canvas = ({ canvasContent, size }) => {
636
665
  }
637
666
  let canceled = false;
638
667
  const handleInstallRequest = async () => {
668
+ var _a;
639
669
  setInstallingElementName(activeElementInstallRequest.element.displayName);
640
- const preflight = await (0, call_api_1.callApi)('/api/prepare-element-install', {
670
+ const preflight = await (0, element_install_api_1.prepareElementInstall)({
641
671
  compositionFile: activeElementInstallRequest.compositionFile,
642
672
  compositionId: activeElementInstallRequest.compositionId,
643
673
  element: activeElementInstallRequest.element,
@@ -661,12 +691,17 @@ const Canvas = ({ canvasContent, size }) => {
661
691
  .map((dependency) => dependency.version === null
662
692
  ? dependency.name
663
693
  : `${dependency.name}@${dependency.version}`);
664
- const sourceLabel = activeElementInstallRequest.source.type === 'studio-protocol'
665
- ? activeElementInstallRequest.source.origin
666
- : 'Unverified drag-and-drop payload';
694
+ const { source } = activeElementInstallRequest;
695
+ const sourceLabel = source.type === 'studio-protocol'
696
+ ? source.origin
697
+ : source.type === 'browser-studio-link'
698
+ ? ((_a = source.origin) !== null && _a !== void 0 ? _a : 'Unverified Browser Studio link')
699
+ : 'Unverified drag-and-drop payload';
700
+ const sourceIsUnverified = source.type === 'drag-and-drop' ||
701
+ (source.type === 'browser-studio-link' && source.origin === null);
667
702
  const accepted = await confirm({
668
703
  title: 'Install Element',
669
- message: (jsx_runtime_1.jsx(ElementInstallConfirmation_1.ElementInstallConfirmation, { displayName: activeElementInstallRequest.element.displayName, sourceLabel: sourceLabel, sourceIsUnverified: activeElementInstallRequest.source.type === 'drag-and-drop', compositionId: activeElementInstallRequest.compositionId, filePath: preflight.plan.filePath, overwritesExistingFile: preflight.plan.expectedFileState.exists, dependenciesToReview: dependenciesToReview, missingPackages: missingPackages, sourceCode: activeElementInstallRequest.element.sourceCode })),
704
+ message: (jsx_runtime_1.jsx(ElementInstallConfirmation_1.ElementInstallConfirmation, { displayName: activeElementInstallRequest.element.displayName, sourceLabel: sourceLabel, sourceIsUnverified: sourceIsUnverified, compositionId: activeElementInstallRequest.compositionId, filePath: preflight.plan.filePath, overwritesExistingFile: preflight.plan.expectedFileState.exists, dependenciesToReview: dependenciesToReview, missingPackages: missingPackages, sourceCode: activeElementInstallRequest.element.sourceCode, usesBrowserDependencyResolution: (0, browser_studio_operations_1.getBrowserStudioOperations)() !== null })),
670
705
  confirmLabel: 'Install',
671
706
  cancelLabel: 'Cancel',
672
707
  });
@@ -6,6 +6,7 @@ const react_1 = require("react");
6
6
  const remotion_1 = require("remotion");
7
7
  const ErrorLoader_1 = require("../error-overlay/remotion-overlay/ErrorLoader");
8
8
  const colors_1 = require("../helpers/colors");
9
+ const composition_list_1 = require("../state/composition-list");
9
10
  const timeline_zoom_1 = require("../state/timeline-zoom");
10
11
  const Canvas_1 = require("./Canvas");
11
12
  const FramePersistor_1 = require("./FramePersistor");
@@ -29,6 +30,7 @@ const CanvasOrLoading = ({ size }) => {
29
30
  const resolved = remotion_1.Internals.useResolvedVideoConfig(null);
30
31
  const { setZoom } = (0, react_1.useContext)(timeline_zoom_1.TimelineZoomCtx);
31
32
  const { canvasContent } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
33
+ const { compositionListState } = (0, react_1.useContext)(composition_list_1.CompositionListContext);
32
34
  const { error: renderError } = (0, react_1.useContext)(RenderErrorContext_1.RenderErrorContext);
33
35
  (0, react_1.useEffect)(() => {
34
36
  if ((resolved === null || resolved === void 0 ? void 0 : resolved.type) !== 'success' &&
@@ -48,6 +50,9 @@ const CanvasOrLoading = ({ size }) => {
48
50
  return (jsx_runtime_1.jsx(ErrorLoading, { error: renderError, calculateMetadataContext: false }));
49
51
  }
50
52
  if (!canvasContent) {
53
+ if (compositionListState !== 'ready') {
54
+ return null;
55
+ }
51
56
  const compname = window.location.pathname.replace('/', '');
52
57
  return (jsx_runtime_1.jsx("div", { style: container, className: "css-reset", children: jsx_runtime_1.jsxs("div", { style: RunningCalculateMetadata_1.loaderLabel, children: ["Composition with ID ", compname, " not found."] }) }));
53
58
  }
@@ -116,6 +116,8 @@ const CompositionSelector = () => {
116
116
  return {
117
117
  flex: 1,
118
118
  overflowY: 'auto',
119
+ paddingTop: 4,
120
+ paddingBottom: 4,
119
121
  backgroundColor: rootDragHovered ? colors_1.WHITE_ALPHA_12 : colors_1.BACKGROUND,
120
122
  };
121
123
  }, [rootDragHovered]);