@remotion/studio 4.0.512 → 4.0.514

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 (208) hide show
  1. package/dist/Studio.js +2 -1
  2. package/dist/components/AskAiModal.js +1 -1
  3. package/dist/components/AssetSelector.js +2 -0
  4. package/dist/components/AssetSelectorItem.js +1 -2
  5. package/dist/components/AudioWaveform.d.ts +3 -0
  6. package/dist/components/AudioWaveform.js +55 -67
  7. package/dist/components/Canvas.js +40 -5
  8. package/dist/components/CanvasOrLoading.js +5 -0
  9. package/dist/components/CompositionSelector.js +2 -0
  10. package/dist/components/CompositionSelectorItem.js +14 -1
  11. package/dist/components/ConfigureDefaultEditorModal.js +17 -11
  12. package/dist/components/Editor.js +16 -1
  13. package/dist/components/ElementInstallConfirmation.d.ts +1 -0
  14. package/dist/components/ElementInstallConfirmation.js +4 -2
  15. package/dist/components/FixComputedValueModal.d.ts +9 -0
  16. package/dist/components/FixComputedValueModal.js +217 -0
  17. package/dist/components/InitialCompositionLoader.js +19 -0
  18. package/dist/components/InlineDropdown.js +4 -4
  19. package/dist/components/InspectorInfoHeader.js +3 -3
  20. package/dist/components/InspectorOpenInEditor.js +26 -24
  21. package/dist/components/InspectorPanel/AlignmentControls.js +13 -2
  22. package/dist/components/InspectorPanel/CompositionInspector.js +11 -1
  23. package/dist/components/InspectorPanel/CompositionInspectorHeader.js +12 -8
  24. package/dist/components/InspectorPanel/ConnectedCompositionsSection.js +13 -2
  25. package/dist/components/InspectorPanel/EasingInspector.js +12 -3
  26. package/dist/components/InspectorPanel/KeyframeInspector.js +21 -7
  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/easing-inspector-selection.js +7 -2
  32. package/dist/components/InspectorPanel/inspector-section-collapse.d.ts +1 -0
  33. package/dist/components/InspectorPanel/styles.d.ts +1 -1
  34. package/dist/components/InspectorPanel/styles.js +4 -2
  35. package/dist/components/InspectorSourceLocation.d.ts +1 -1
  36. package/dist/components/InspectorSourceLocation.js +2 -2
  37. package/dist/components/LicenseKeyValidation.js +2 -2
  38. package/dist/components/Modals.js +2 -1
  39. package/dist/components/NewComposition/CodemodFooter.d.ts +1 -0
  40. package/dist/components/NewComposition/CodemodFooter.js +10 -8
  41. package/dist/components/NewComposition/DeleteComposition.js +1 -1
  42. package/dist/components/NewComposition/DeleteFolder.js +1 -1
  43. package/dist/components/NewComposition/DuplicateComposition.js +7 -2
  44. package/dist/components/NewComposition/NewComposition.js +1 -1
  45. package/dist/components/NewComposition/NewFolder.js +1 -1
  46. package/dist/components/NewComposition/RenameComposition.js +1 -1
  47. package/dist/components/NewComposition/RenameFolder.js +1 -1
  48. package/dist/components/NewComposition/duplicate-composition-api.d.ts +16 -0
  49. package/dist/components/NewComposition/duplicate-composition-api.js +16 -0
  50. package/dist/components/NoRegisterRoot.js +1 -1
  51. package/dist/components/QuickSwitcher/ExplorerQuickSwitcherTrigger.js +4 -3
  52. package/dist/components/QuickSwitcher/QuickSwitcherContent.js +1 -0
  53. package/dist/components/QuickSwitcher/fuzzy-search.js +1 -1
  54. package/dist/components/RefreshCompositionOverlay.js +1 -1
  55. package/dist/components/RenderButton.js +6 -3
  56. package/dist/components/RenderModal/WebRenderModal.js +6 -2
  57. package/dist/components/RenderModal/WebRenderModalAdvanced.d.ts +2 -0
  58. package/dist/components/RenderModal/WebRenderModalAdvanced.js +9 -2
  59. package/dist/components/RenderModal/render-modals.js +5 -1
  60. package/dist/components/RenderQueue/ClientRenderQueueProcessor.js +5 -1
  61. package/dist/components/RenderQueue/actions.js +12 -2
  62. package/dist/components/RenderQueue/client-side-render-types.d.ts +1 -0
  63. package/dist/components/RenderingSettings.d.ts +2 -0
  64. package/dist/components/RenderingSettings.js +355 -0
  65. package/dist/components/SelectedOutlineElement.js +15 -13
  66. package/dist/components/SelectedOutlineOverlay.js +30 -8
  67. package/dist/components/SelectedOutlinePolygon.d.ts +1 -0
  68. package/dist/components/SelectedOutlinePolygon.js +53 -9
  69. package/dist/components/SettingsContext.d.ts +4 -1
  70. package/dist/components/SettingsContext.js +9 -2
  71. package/dist/components/SettingsModal.d.ts +1 -1
  72. package/dist/components/SettingsModal.js +10 -1
  73. package/dist/components/SettingsModalFooter.js +1 -1
  74. package/dist/components/StudioSettings.d.ts +2 -0
  75. package/dist/components/StudioSettings.js +185 -0
  76. package/dist/components/Timeline/LoopedIndicator.js +1 -1
  77. package/dist/components/Timeline/LoopedTimelineIndicators.d.ts +3 -0
  78. package/dist/components/Timeline/LoopedTimelineIndicators.js +22 -14
  79. package/dist/components/Timeline/Timeline.js +11 -9
  80. package/dist/components/Timeline/TimelineArrayField.js +1 -0
  81. package/dist/components/Timeline/TimelineAssetField.d.ts +2 -2
  82. package/dist/components/Timeline/TimelineAssetField.js +1 -1
  83. package/dist/components/Timeline/TimelineDragHandler.js +62 -76
  84. package/dist/components/Timeline/TimelineEffectItem.js +1 -1
  85. package/dist/components/Timeline/TimelineEffectPropItem.d.ts +4 -2
  86. package/dist/components/Timeline/TimelineEffectPropItem.js +25 -14
  87. package/dist/components/Timeline/TimelineExpandedRow.d.ts +1 -1
  88. package/dist/components/Timeline/TimelineExpandedRow.js +4 -4
  89. package/dist/components/Timeline/TimelineExpandedSection.js +1 -1
  90. package/dist/components/Timeline/TimelineHeightContainer.d.ts +0 -4
  91. package/dist/components/Timeline/TimelineHeightContainer.js +4 -4
  92. package/dist/components/Timeline/TimelineImageInfo.d.ts +1 -0
  93. package/dist/components/Timeline/TimelineImageInfo.js +3 -2
  94. package/dist/components/Timeline/TimelineKeyframeControls.js +31 -8
  95. package/dist/components/Timeline/TimelineKeyframedValue.js +1 -0
  96. package/dist/components/Timeline/TimelineList.d.ts +1 -5
  97. package/dist/components/Timeline/TimelineList.js +14 -9
  98. package/dist/components/Timeline/TimelinePinchZoom.js +5 -5
  99. package/dist/components/Timeline/TimelineRowChrome.d.ts +0 -2
  100. package/dist/components/Timeline/TimelineRowChrome.js +12 -5
  101. package/dist/components/Timeline/TimelineSchemaField.d.ts +7 -3
  102. package/dist/components/Timeline/TimelineSchemaField.js +71 -13
  103. package/dist/components/Timeline/TimelineScrollable.js +3 -1
  104. package/dist/components/Timeline/TimelineSelection.d.ts +5 -2
  105. package/dist/components/Timeline/TimelineSelection.js +90 -103
  106. package/dist/components/Timeline/TimelineSequence.js +59 -25
  107. package/dist/components/Timeline/TimelineSequenceItem.d.ts +1 -1
  108. package/dist/components/Timeline/TimelineSequenceItem.js +15 -9
  109. package/dist/components/Timeline/TimelineSequencePropItem.d.ts +2 -1
  110. package/dist/components/Timeline/TimelineSequencePropItem.js +14 -7
  111. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.d.ts +3 -0
  112. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +128 -27
  113. package/dist/components/Timeline/TimelineSlider.js +42 -33
  114. package/dist/components/Timeline/TimelineTimeIndicators.js +90 -98
  115. package/dist/components/Timeline/TimelineTracks.d.ts +0 -2
  116. package/dist/components/Timeline/TimelineTracks.js +11 -4
  117. package/dist/components/Timeline/TimelineTransformOriginField.js +1 -1
  118. package/dist/components/Timeline/TimelineVideoInfo.d.ts +4 -4
  119. package/dist/components/Timeline/TimelineVideoInfo.js +151 -61
  120. package/dist/components/Timeline/TimelineViewport.d.ts +12 -0
  121. package/dist/components/Timeline/TimelineViewport.js +62 -0
  122. package/dist/components/Timeline/TimelineVirtualization.d.ts +22 -0
  123. package/dist/components/Timeline/TimelineVirtualization.js +144 -0
  124. package/dist/components/Timeline/TimelineZoomControls.js +16 -8
  125. package/dist/components/Timeline/call-add-keyframe.js +31 -3
  126. package/dist/components/Timeline/call-delete-keyframe.js +13 -3
  127. package/dist/components/Timeline/call-move-keyframe.d.ts +2 -1
  128. package/dist/components/Timeline/call-move-keyframe.js +81 -18
  129. package/dist/components/Timeline/call-update-keyframe-settings.js +31 -3
  130. package/dist/components/Timeline/delete-selected-keyframe.d.ts +0 -8
  131. package/dist/components/Timeline/delete-selected-keyframe.js +23 -44
  132. package/dist/components/Timeline/delete-selected-timeline-item.d.ts +0 -8
  133. package/dist/components/Timeline/delete-selected-timeline-item.js +18 -44
  134. package/dist/components/Timeline/get-easing-selection-after-keyframe-delete.js +8 -3
  135. package/dist/components/Timeline/get-sequence-context-menu-items.js +10 -8
  136. package/dist/components/Timeline/get-timeline-keyframes.d.ts +5 -2
  137. package/dist/components/Timeline/get-timeline-keyframes.js +16 -10
  138. package/dist/components/Timeline/get-timeline-sequence-visible-layout.d.ts +30 -0
  139. package/dist/components/Timeline/get-timeline-sequence-visible-layout.js +61 -0
  140. package/dist/components/Timeline/keyframe-clipboard.js +9 -2
  141. package/dist/components/Timeline/split-selected-timeline-item.js +2 -2
  142. package/dist/components/Timeline/timeline-scroll-logic.d.ts +24 -0
  143. package/dist/components/Timeline/timeline-scroll-logic.js +127 -4
  144. package/dist/components/Timeline/use-open-sequence-in-apps.js +8 -8
  145. package/dist/components/Timeline/use-timeline-height.d.ts +3 -5
  146. package/dist/components/Timeline/use-timeline-height.js +16 -18
  147. package/dist/components/Timeline/use-timeline-keyframe-drag.js +14 -4
  148. package/dist/components/UpdateCheck.d.ts +2 -10
  149. package/dist/components/UpdateCheck.js +8 -2
  150. package/dist/components/VisualControls/ClickableFileName.js +13 -6
  151. package/dist/components/VisualControls/VisualControlHandle.js +8 -0
  152. package/dist/components/composition-menu-items.d.ts +6 -1
  153. package/dist/components/composition-menu-items.js +9 -6
  154. package/dist/components/delete-jsx-node-api.d.ts +2 -0
  155. package/dist/components/delete-jsx-node-api.js +12 -0
  156. package/dist/components/element-install-api.d.ts +3 -0
  157. package/dist/components/element-install-api.js +19 -0
  158. package/dist/components/folder-menu-items.d.ts +4 -1
  159. package/dist/components/folder-menu-items.js +4 -5
  160. package/dist/components/get-open-in-menu-items.d.ts +1 -1
  161. package/dist/components/get-open-in-menu-items.js +15 -13
  162. package/dist/components/import-assets.js +20 -9
  163. package/dist/components/reorder-sequence-api.d.ts +2 -0
  164. package/dist/components/reorder-sequence-api.js +12 -0
  165. package/dist/components/sequence-props-api.js +44 -3
  166. package/dist/components/split-jsx-sequence-api.d.ts +2 -0
  167. package/dist/components/split-jsx-sequence-api.js +12 -0
  168. package/dist/components/split-video-from-audio-api.d.ts +2 -0
  169. package/dist/components/split-video-from-audio-api.js +12 -0
  170. package/dist/components/use-default-editor-info.d.ts +8 -0
  171. package/dist/components/use-default-editor-info.js +25 -9
  172. package/dist/error-overlay/remotion-overlay/ErrorDisplay.js +10 -3
  173. package/dist/error-overlay/remotion-overlay/OpenInEditor.d.ts +3 -1
  174. package/dist/error-overlay/remotion-overlay/OpenInEditor.js +6 -6
  175. package/dist/error-overlay/remotion-overlay/Overlay.js +14 -12
  176. package/dist/error-overlay/remotion-overlay/StackFrame.d.ts +2 -1
  177. package/dist/error-overlay/remotion-overlay/StackFrame.js +7 -4
  178. package/dist/esm/{chunk-s8gwjng0.js → chunk-xn2q7eem.js} +11983 -8035
  179. package/dist/esm/index.mjs +7 -5
  180. package/dist/esm/internals.mjs +11983 -8035
  181. package/dist/esm/previewEntry.mjs +13059 -9107
  182. package/dist/esm/renderEntry.mjs +2 -3
  183. package/dist/helpers/browser-studio-operations.d.ts +2 -0
  184. package/dist/helpers/browser-studio-operations.js +10 -1
  185. package/dist/helpers/get-timeline-max-zoom.d.ts +26 -0
  186. package/dist/helpers/get-timeline-max-zoom.js +45 -0
  187. package/dist/helpers/inject-css.js +2 -2
  188. package/dist/helpers/open-in-editor.d.ts +6 -4
  189. package/dist/helpers/open-in-editor.js +4 -4
  190. package/dist/helpers/render-codec-label.d.ts +1 -1
  191. package/dist/helpers/retry-payload.js +1 -0
  192. package/dist/helpers/studio-runtime-config.d.ts +1 -1
  193. package/dist/helpers/studio-runtime-config.js +2 -3
  194. package/dist/helpers/timeline-layout.d.ts +3 -1
  195. package/dist/helpers/timeline-layout.js +6 -1
  196. package/dist/helpers/url-state.js +3 -2
  197. package/dist/helpers/use-menu-structure.js +12 -11
  198. package/dist/helpers/use-runtime-values.d.ts +2 -1
  199. package/dist/helpers/use-runtime-values.js +7 -3
  200. package/dist/icons/remotion-triangle.d.ts +2 -0
  201. package/dist/icons/remotion-triangle.js +7 -0
  202. package/dist/renderEntry.js +1 -1
  203. package/dist/state/composition-list.d.ts +13 -0
  204. package/dist/state/composition-list.js +21 -0
  205. package/dist/state/modals.d.ts +7 -1
  206. package/dist/state/timeline-zoom.d.ts +1 -2
  207. package/dist/state/timeline-zoom.js +9 -5
  208. package/package.json +14 -13
@@ -56,7 +56,7 @@ const focus_inspector_field_1 = require("./Timeline/focus-inspector-field");
56
56
  const imperative_state_1 = require("./Timeline/imperative-state");
57
57
  const save_sequence_prop_1 = require("./Timeline/save-sequence-prop");
58
58
  const should_clear_selection_on_pointer_down_1 = require("./Timeline/should-clear-selection-on-pointer-down");
59
- const SelectedOutlinePolygonUnmemoized = ({ compositionHeight, compositionWidth, dragging, getAllDragOutlines, getAllDragTargets, getLayoutTarget, getTarget, hasTarget, hovered, onContextMenuOpen, onContextMenuOpenChange, outline, onDraggingChange, onHoverChange, onSnapPointsChange, onSelect, onDoubleClickTarget, scale, showSelectedOutline, }) => {
59
+ const SelectedOutlinePolygonUnmemoized = ({ compositionHeight, compositionWidth, directlySelected, dragging, getAllDragOutlines, getAllDragTargets, getLayoutTarget, getTarget, hasTarget, hovered, onContextMenuOpen, onContextMenuOpenChange, outline, onDraggingChange, onHoverChange, onSnapPointsChange, onSelect, onDoubleClickTarget, scale, showSelectedOutline, }) => {
60
60
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
61
61
  const { canvasContent } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
62
62
  const { getDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeDragOverridesContext);
@@ -85,6 +85,7 @@ const SelectedOutlinePolygonUnmemoized = ({ compositionHeight, compositionWidth,
85
85
  };
86
86
  }, [getLayoutTarget, previewServerState]);
87
87
  const onPointerDown = react_1.default.useCallback((event) => {
88
+ var _a;
88
89
  const target = getTarget();
89
90
  if (event.button !== 0 || target === undefined) {
90
91
  return;
@@ -94,23 +95,63 @@ const SelectedOutlinePolygonUnmemoized = ({ compositionHeight, compositionWidth,
94
95
  event.stopPropagation();
95
96
  const interaction = (0, selected_outline_measurement_1.getOutlineSelectionInteraction)(event);
96
97
  const shouldUpdateSelection = !selected || interaction.shiftKey || interaction.toggleKey;
97
- if (shouldUpdateSelection) {
98
+ const ownerSvg = (_a = polygonRef.current) === null || _a === void 0 ? void 0 : _a.ownerSVGElement;
99
+ let pointerInsideSelectedOutline = false;
100
+ if (ownerSvg) {
101
+ const screenPoint = ownerSvg.createSVGPoint();
102
+ screenPoint.x = event.clientX;
103
+ screenPoint.y = event.clientY;
104
+ pointerInsideSelectedOutline = Array.from(ownerSvg.querySelectorAll('polygon[data-remotion-directly-selected-outline="true"]')).some((selectedPolygon) => {
105
+ const screenTransform = selectedPolygon.getScreenCTM();
106
+ if (screenTransform === null) {
107
+ return false;
108
+ }
109
+ const polygonPoint = screenPoint.matrixTransform(screenTransform.inverse());
110
+ return (selectedPolygon.isPointInFill(polygonPoint) ||
111
+ selectedPolygon.isPointInStroke(polygonPoint));
112
+ });
113
+ }
114
+ const deferSelection = !selected &&
115
+ !interaction.shiftKey &&
116
+ !interaction.toggleKey &&
117
+ pointerInsideSelectedOutline;
118
+ if (!deferSelection && shouldUpdateSelection) {
98
119
  onSelect(target.selection, interaction);
99
120
  }
100
- if (drag === null || interaction.shiftKey || interaction.toggleKey) {
121
+ if (interaction.shiftKey ||
122
+ interaction.toggleKey ||
123
+ (drag === null && !deferSelection)) {
101
124
  return;
102
125
  }
103
126
  if ((0, focus_inspector_field_1.commitPendingInspectorFields)()) {
127
+ if (deferSelection) {
128
+ onSelect(target.selection, interaction);
129
+ }
104
130
  return;
105
131
  }
106
132
  const startPointerX = event.clientX;
107
133
  const startPointerY = event.clientY;
134
+ const dragExistingSelection = selected || deferSelection;
135
+ const dragTargets = dragExistingSelection
136
+ ? getAllDragTargets()
137
+ : drag === null
138
+ ? []
139
+ : [drag];
140
+ if (dragTargets.length === 0) {
141
+ if (deferSelection) {
142
+ onSelect(target.selection, interaction);
143
+ }
144
+ return;
145
+ }
108
146
  const dragStates = (0, selected_outline_drag_1.getSelectedOutlineDragStates)({
109
- dragTargets: selected ? getAllDragTargets() : [drag],
147
+ dragTargets,
110
148
  getDragOverrides,
111
149
  timelinePosition: (0, imperative_state_1.getCurrentFrame)(),
112
150
  });
113
- const dragOutlines = selected ? getAllDragOutlines() : [outline];
151
+ const dragOutlines = dragExistingSelection
152
+ ? getAllDragOutlines()
153
+ : [outline];
154
+ const [{ clientId }] = dragTargets;
114
155
  let lastValues = new Map();
115
156
  let currentPointerX = startPointerX;
116
157
  let currentPointerY = startPointerY;
@@ -212,7 +253,7 @@ const SelectedOutlinePolygonUnmemoized = ({ compositionHeight, compositionWidth,
212
253
  axisLocked = nextAxisLocked;
213
254
  updateDragOverrides();
214
255
  };
215
- const onPointerUp = () => {
256
+ const onPointerUp = (reason) => {
216
257
  window.removeEventListener('keydown', onKeyChange);
217
258
  window.removeEventListener('keyup', onKeyChange);
218
259
  if (dragStarted) {
@@ -226,6 +267,9 @@ const SelectedOutlinePolygonUnmemoized = ({ compositionHeight, compositionWidth,
226
267
  });
227
268
  if (changes.length === 0) {
228
269
  (0, selected_outline_drag_1.clearSelectedOutlineDragOverrides)({ clearDragOverrides, dragStates });
270
+ if (deferSelection && !dragStarted && reason === 'pointerup') {
271
+ onSelect(target.selection, interaction);
272
+ }
229
273
  return;
230
274
  }
231
275
  const staticChanges = changes.filter((change) => change.type === 'static');
@@ -237,7 +281,7 @@ const SelectedOutlinePolygonUnmemoized = ({ compositionHeight, compositionWidth,
237
281
  addedKeyframes: null,
238
282
  movedKeyframes: null,
239
283
  setPropStatuses,
240
- clientId: drag.clientId,
284
+ clientId,
241
285
  undoLabel: changes.length > 1
242
286
  ? 'Move selected sequences'
243
287
  : 'Move sequence',
@@ -250,7 +294,7 @@ const SelectedOutlinePolygonUnmemoized = ({ compositionHeight, compositionWidth,
250
294
  sequenceKeyframes: keyframedChanges,
251
295
  effectKeyframes: [],
252
296
  setPropStatuses,
253
- clientId: drag.clientId,
297
+ clientId,
254
298
  }),
255
299
  ])
256
300
  .catch((err) => {
@@ -347,7 +391,7 @@ const SelectedOutlinePolygonUnmemoized = ({ compositionHeight, compositionWidth,
347
391
  });
348
392
  }, [getEffectDropTarget]);
349
393
  return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
350
- jsx_runtime_1.jsx("polygon", { ref: polygonRef, [should_clear_selection_on_pointer_down_1.PREVENT_CLEAR_SELECTION_ON_POINTER_DOWN_ATTR]: 'true', points: points, fill: effectDropHovered ? colors_1.TIMELINE_DROP_BLUE_ALPHA_12 : colors_1.TRANSPARENT, stroke: colors_1.BLUE, strokeOpacity: visible || effectDropHovered ? 1 : 0, strokeWidth: 2, vectorEffect: "non-scaling-stroke", pointerEvents: hasTarget ? 'all' : undefined, onPointerEnter: () => {
394
+ jsx_runtime_1.jsx("polygon", { ref: polygonRef, [should_clear_selection_on_pointer_down_1.PREVENT_CLEAR_SELECTION_ON_POINTER_DOWN_ATTR]: 'true', "data-remotion-directly-selected-outline": directlySelected ? 'true' : undefined, points: points, fill: effectDropHovered ? colors_1.TIMELINE_DROP_BLUE_ALPHA_12 : colors_1.TRANSPARENT, stroke: colors_1.BLUE, strokeOpacity: visible || effectDropHovered ? 1 : 0, strokeWidth: 2, vectorEffect: "non-scaling-stroke", pointerEvents: hasTarget ? 'all' : undefined, onPointerEnter: () => {
351
395
  if (!dragging) {
352
396
  onHoverChange(outline.key);
353
397
  }
@@ -1,10 +1,13 @@
1
- import type { GetDefaultCodingAgentInfoResponse, GetDefaultEditorInfoResponse } from '@remotion/studio-shared';
1
+ import type { GetDefaultCodingAgentInfoResponse, GetDefaultEditorInfoResponse, GetRemotionSkillsInfoResponse, RenderDefaults, StudioRuntimeConfig } from '@remotion/studio-shared';
2
2
  import React from 'react';
3
3
  type SettingsContextValue = {
4
4
  readonly codingAgentInfo: GetDefaultCodingAgentInfoResponse | null;
5
5
  readonly editorInfo: GetDefaultEditorInfoResponse | null;
6
6
  readonly error: string | null;
7
7
  readonly publicLicenseKey: string | null;
8
+ readonly remotionSkillsInfo: GetRemotionSkillsInfoResponse | null;
9
+ readonly renderDefaults: RenderDefaults | null;
10
+ readonly studioRuntimeConfig: StudioRuntimeConfig | null;
8
11
  readonly revision: number;
9
12
  readonly setPublicLicenseKey: (publicLicenseKey: string | null) => void;
10
13
  };
@@ -9,13 +9,16 @@ const call_api_1 = require("./call-api");
9
9
  const SettingsContext = (0, react_1.createContext)(null);
10
10
  const SettingsProvider = ({ children }) => {
11
11
  var _a;
12
- var _b;
12
+ var _b, _c, _d;
13
13
  const { previewServerState, subscribeToEvent } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
14
14
  const [settings, setSettings] = (0, react_1.useState)({
15
15
  codingAgentInfo: null,
16
16
  editorInfo: null,
17
17
  error: null,
18
18
  publicLicenseKey: (_b = (_a = window.remotion_studioConfig) === null || _a === void 0 ? void 0 : _a.publicLicenseKey) !== null && _b !== void 0 ? _b : null,
19
+ remotionSkillsInfo: null,
20
+ renderDefaults: (_c = window.remotion_renderDefaults) !== null && _c !== void 0 ? _c : null,
21
+ studioRuntimeConfig: (_d = window.remotion_studioConfig) !== null && _d !== void 0 ? _d : null,
19
22
  revision: 0,
20
23
  });
21
24
  (0, react_1.useEffect)(() => {
@@ -31,8 +34,9 @@ const SettingsProvider = ({ children }) => {
31
34
  Promise.all([
32
35
  (0, call_api_1.callApi)('/api/default-editor-info', {}, controller.signal),
33
36
  (0, call_api_1.callApi)('/api/default-coding-agent-info', {}, controller.signal),
37
+ (0, call_api_1.callApi)('/api/remotion-skills-info', {}, controller.signal),
34
38
  ])
35
- .then(([editorInfo, codingAgentInfo]) => {
39
+ .then(([editorInfo, codingAgentInfo, remotionSkillsInfo]) => {
36
40
  const runtimeConfig = window.remotion_studioConfig;
37
41
  setSettings((currentSettings) => ({
38
42
  ...currentSettings,
@@ -48,6 +52,7 @@ const SettingsProvider = ({ children }) => {
48
52
  ? runtimeConfig.defaultEditor
49
53
  : editorInfo.defaultEditor,
50
54
  },
55
+ remotionSkillsInfo,
51
56
  error: null,
52
57
  revision: currentSettings.revision + 1,
53
58
  }));
@@ -84,6 +89,8 @@ const SettingsProvider = ({ children }) => {
84
89
  : null,
85
90
  error: null,
86
91
  publicLicenseKey: event.studioRuntimeConfig.publicLicenseKey,
92
+ renderDefaults: event.renderDefaults,
93
+ studioRuntimeConfig: event.studioRuntimeConfig,
87
94
  revision: currentSettings.revision + 1,
88
95
  }));
89
96
  });
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- type SettingsTab = 'apps' | 'license';
2
+ type SettingsTab = 'apps' | 'rendering' | 'studio' | 'license';
3
3
  export declare const SettingsModal: React.FC<{
4
4
  readonly initialTab: SettingsTab;
5
5
  readonly initialPublicLicenseKey: string | null;
@@ -5,19 +5,28 @@ const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const apps_1 = require("../icons/apps");
7
7
  const certificate_1 = require("../icons/certificate");
8
+ const remotion_triangle_1 = require("../icons/remotion-triangle");
9
+ const video_1 = require("../icons/video");
8
10
  const modals_1 = require("../state/modals");
9
11
  const ConfigureDefaultEditorModal_1 = require("./ConfigureDefaultEditorModal");
10
12
  const ConfigureLicenseModal_1 = require("./ConfigureLicenseModal");
11
13
  const is_menu_item_1 = require("./Menu/is-menu-item");
12
14
  const ModalHeader_1 = require("./ModalHeader");
13
15
  const DismissableModal_1 = require("./NewComposition/DismissableModal");
16
+ const RenderingSettings_1 = require("./RenderingSettings");
14
17
  const render_modals_1 = require("./RenderModal/render-modals");
15
18
  const SettingsContext_1 = require("./SettingsContext");
16
19
  const SettingsModalFooter_1 = require("./SettingsModalFooter");
20
+ const StudioSettings_1 = require("./StudioSettings");
17
21
  const vertical_1 = require("./Tabs/vertical");
18
22
  const hiddenPanel = {
19
23
  display: 'none',
20
24
  };
25
+ const settingsOptionsPanel = {
26
+ ...render_modals_1.optionsPanel,
27
+ boxSizing: 'border-box',
28
+ paddingBottom: 16,
29
+ };
21
30
  const appsIcon = {
22
31
  ...render_modals_1.icon,
23
32
  height: 20,
@@ -50,7 +59,7 @@ const SettingsModal = ({ initialPublicLicenseKey, initialTab }) => {
50
59
  }, [initialPublicLicenseKey, setPublicLicenseKey]);
51
60
  return (jsx_runtime_1.jsx(DismissableModal_1.DismissableModal, { panelStyle: render_modals_1.outerModalStyle, children: jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
52
61
  jsx_runtime_1.jsx(ModalHeader_1.ModalHeader, { title: "Settings", onClose: dismiss }), jsx_runtime_1.jsxs("div", { style: render_modals_1.horizontalLayout, children: [
53
- jsx_runtime_1.jsxs("div", { style: render_modals_1.leftSidebar, children: [jsx_runtime_1.jsx(vertical_1.VerticalTab, { style: render_modals_1.horizontalTab, selected: tab === 'apps', onClick: () => selectTab('apps'), renderIcon: (color) => (jsx_runtime_1.jsx("div", { style: appsIconContainer, children: jsx_runtime_1.jsx(apps_1.AppsIcon, { color: color, style: appsIcon }) })), children: "Apps" }), jsx_runtime_1.jsx(vertical_1.VerticalTab, { style: render_modals_1.horizontalTab, selected: tab === 'license', onClick: () => selectTab('license'), renderIcon: (color) => (jsx_runtime_1.jsx("div", { style: render_modals_1.iconContainer, children: jsx_runtime_1.jsx(certificate_1.CertificateIcon, { color: color, style: render_modals_1.icon }) })), children: "License" })] }), openedTabs.includes('apps') ? (jsx_runtime_1.jsx("div", { style: tab === 'apps' ? render_modals_1.optionsPanel : hiddenPanel, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: jsx_runtime_1.jsx(ConfigureDefaultEditorModal_1.DefaultEditorSettings, {}) })) : null, openedTabs.includes('license') ? (jsx_runtime_1.jsx("div", { style: tab === 'license' ? render_modals_1.optionsPanel : hiddenPanel, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: jsx_runtime_1.jsx(ConfigureLicenseModal_1.LicenseSettings, {}) })) : null] }), jsx_runtime_1.jsx(SettingsModalFooter_1.SettingsModalFooter, {})
62
+ jsx_runtime_1.jsxs("div", { style: render_modals_1.leftSidebar, children: [jsx_runtime_1.jsx(vertical_1.VerticalTab, { style: render_modals_1.horizontalTab, selected: tab === 'rendering', onClick: () => selectTab('rendering'), renderIcon: (color) => (jsx_runtime_1.jsx("div", { style: render_modals_1.iconContainer, children: jsx_runtime_1.jsx(video_1.FilmIcon, { color: color, style: render_modals_1.icon }) })), children: "Defaults" }), jsx_runtime_1.jsx(vertical_1.VerticalTab, { style: render_modals_1.horizontalTab, selected: tab === 'studio', onClick: () => selectTab('studio'), renderIcon: (color) => (jsx_runtime_1.jsx("div", { style: render_modals_1.iconContainer, children: jsx_runtime_1.jsx(remotion_triangle_1.RemotionTriangleIcon, { color: color, style: render_modals_1.icon }) })), children: "Studio" }), jsx_runtime_1.jsx(vertical_1.VerticalTab, { style: render_modals_1.horizontalTab, selected: tab === 'apps', onClick: () => selectTab('apps'), renderIcon: (color) => (jsx_runtime_1.jsx("div", { style: appsIconContainer, children: jsx_runtime_1.jsx(apps_1.AppsIcon, { color: color, style: appsIcon }) })), children: "Apps" }), jsx_runtime_1.jsx(vertical_1.VerticalTab, { style: render_modals_1.horizontalTab, selected: tab === 'license', onClick: () => selectTab('license'), renderIcon: (color) => (jsx_runtime_1.jsx("div", { style: render_modals_1.iconContainer, children: jsx_runtime_1.jsx(certificate_1.CertificateIcon, { color: color, style: render_modals_1.icon }) })), children: "License" })] }), openedTabs.includes('apps') ? (jsx_runtime_1.jsx("div", { style: tab === 'apps' ? settingsOptionsPanel : hiddenPanel, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: jsx_runtime_1.jsx(ConfigureDefaultEditorModal_1.DefaultEditorSettings, {}) })) : null, openedTabs.includes('license') ? (jsx_runtime_1.jsx("div", { style: tab === 'license' ? settingsOptionsPanel : hiddenPanel, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: jsx_runtime_1.jsx(ConfigureLicenseModal_1.LicenseSettings, {}) })) : null, openedTabs.includes('rendering') ? (jsx_runtime_1.jsx("div", { style: tab === 'rendering' ? settingsOptionsPanel : hiddenPanel, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: jsx_runtime_1.jsx(RenderingSettings_1.RenderingSettings, {}) })) : null, openedTabs.includes('studio') ? (jsx_runtime_1.jsx("div", { style: tab === 'studio' ? settingsOptionsPanel : hiddenPanel, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: jsx_runtime_1.jsx(StudioSettings_1.StudioSettings, {}) })) : null] }), jsx_runtime_1.jsx(SettingsModalFooter_1.SettingsModalFooter, {})
54
63
  ] }) }));
55
64
  };
56
65
  exports.SettingsModal = SettingsModal;
@@ -37,7 +37,7 @@ const SettingsModalFooter = () => {
37
37
  column: 1,
38
38
  };
39
39
  }, []);
40
- return (jsx_runtime_1.jsx(ModalFooter_1.ModalFooterContainer, { style: footer, noBorder: true, children: jsx_runtime_1.jsx("div", { style: footerRow, children: jsx_runtime_1.jsxs("div", { style: configFileHint, children: ["Changes save to",
40
+ return (jsx_runtime_1.jsx(ModalFooter_1.ModalFooterContainer, { style: footer, children: jsx_runtime_1.jsx("div", { style: footerRow, children: jsx_runtime_1.jsxs("div", { style: configFileHint, children: ["Changes save to",
41
41
  jsx_runtime_1.jsx(InspectorOpenInEditor_1.InspectorOpenInEditor, { locationType: null, location: configFileLocation, label: jsx_runtime_1.jsx("strong", { style: configFileName, children: "remotion.config.ts" }) })
42
42
  ] }) }) }));
43
43
  };
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export declare const StudioSettings: React.FC;
@@ -0,0 +1,185 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.StudioSettings = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const client_1 = require("@remotion/renderer/client");
6
+ const studio_shared_1 = require("@remotion/studio-shared");
7
+ const react_1 = require("react");
8
+ const colors_1 = require("../helpers/colors");
9
+ const Checkmark_1 = require("../icons/Checkmark");
10
+ const undo_1 = require("../icons/undo");
11
+ const Button_1 = require("./Button");
12
+ const styles_1 = require("./InspectorPanel/styles");
13
+ const layout_1 = require("./layout");
14
+ const ComboBox_1 = require("./NewComposition/ComboBox");
15
+ const InputDragger_1 = require("./NewComposition/InputDragger");
16
+ const ValidationMessage_1 = require("./NewComposition/ValidationMessage");
17
+ const layout_2 = require("./RenderModal/layout");
18
+ const RenderModalHr_1 = require("./RenderModal/RenderModalHr");
19
+ const SettingsContext_1 = require("./SettingsContext");
20
+ const use_auto_save_config_1 = require("./use-auto-save-config");
21
+ const container = {
22
+ display: 'flex',
23
+ flex: 1,
24
+ flexDirection: 'column',
25
+ minWidth: 0,
26
+ };
27
+ const dividerLabel = {
28
+ ...styles_1.sectionHeader,
29
+ margin: 0,
30
+ padding: '4px 16px',
31
+ };
32
+ const controlWidth = {
33
+ boxSizing: 'border-box',
34
+ width: 180,
35
+ };
36
+ const resetIcon = {
37
+ height: 12,
38
+ width: 12,
39
+ };
40
+ const DEFAULT_VALUE = 'studio-default';
41
+ const initialSettings = {
42
+ askAIEnabled: null,
43
+ audioLatencyHint: null,
44
+ beepOnFinish: null,
45
+ enableCrossSiteIsolation: null,
46
+ interactivityEnabled: null,
47
+ keyboardShortcutsEnabled: null,
48
+ logLevel: null,
49
+ maxTimelineTracks: null,
50
+ numberOfSharedAudioTags: null,
51
+ rspack: null,
52
+ };
53
+ const ConfigSelect = ({ defaultLabel, name, onChange, options, value, }) => {
54
+ const values = [
55
+ {
56
+ id: DEFAULT_VALUE,
57
+ keyHint: null,
58
+ label: `Default (${defaultLabel})`,
59
+ leftItem: value === null ? jsx_runtime_1.jsx(Checkmark_1.Checkmark, {}) : null,
60
+ onClick: () => onChange(null),
61
+ quickSwitcherLabel: null,
62
+ subMenu: null,
63
+ type: 'item',
64
+ value: DEFAULT_VALUE,
65
+ },
66
+ { id: `${DEFAULT_VALUE}-divider`, type: 'divider' },
67
+ ...options.map((option) => {
68
+ const id = `${name}-${String(option.value)}`;
69
+ return {
70
+ id,
71
+ keyHint: null,
72
+ label: option.label,
73
+ leftItem: value === option.value ? jsx_runtime_1.jsx(Checkmark_1.Checkmark, {}) : null,
74
+ onClick: () => onChange(option.value),
75
+ quickSwitcherLabel: null,
76
+ subMenu: null,
77
+ type: 'item',
78
+ value: id,
79
+ };
80
+ }),
81
+ ];
82
+ return (jsx_runtime_1.jsxs("div", { style: layout_2.optionRow, children: [
83
+ jsx_runtime_1.jsx("div", { style: layout_2.label, children: name }), jsx_runtime_1.jsx("div", { style: layout_2.rightRow, children: jsx_runtime_1.jsx(ComboBox_1.Combobox, { values: values, selectedId: value === null ? DEFAULT_VALUE : `${name}-${String(value)}`, style: controlWidth, title: name }) })
84
+ ] }));
85
+ };
86
+ const ConfigNumber = ({ defaultLabel, defaultValue, name, onChange, onChangeEnd, value, }) => {
87
+ const resolvedDefaultLabel = defaultLabel !== null && defaultLabel !== void 0 ? defaultLabel : String(defaultValue);
88
+ return (jsx_runtime_1.jsxs("div", { style: layout_2.optionRow, children: [
89
+ jsx_runtime_1.jsx("div", { style: layout_2.label, children: name }), jsx_runtime_1.jsxs("div", { style: { ...layout_2.rightRow, gap: 6 }, children: [
90
+ jsx_runtime_1.jsx(InputDragger_1.InputDragger, { "aria-label": name, buttonStyle: { textAlign: 'right', width: 140 }, formatter: () => value === null ? `Default (${resolvedDefaultLabel})` : String(value), min: 0, onTextChange: () => undefined, onValueChange: onChange, onValueChangeEnd: onChangeEnd, placeholder: `Default (${resolvedDefaultLabel})`, rightAlign: true, status: "ok", step: 1, value: value !== null && value !== void 0 ? value : defaultValue }), jsx_runtime_1.jsx(Button_1.Button, { disabled: value === null, onClick: () => onChangeEnd(null), size: "compact", style: { color: colors_1.LIGHT_TEXT }, title: `Use default (${resolvedDefaultLabel})`, children: jsx_runtime_1.jsx(undo_1.UndoIcon, { style: resetIcon }) })
91
+ ] })
92
+ ] }));
93
+ };
94
+ const booleanOptions = [
95
+ { label: 'Enabled', value: true },
96
+ { label: 'Disabled', value: false },
97
+ ];
98
+ const StudioSettings = () => {
99
+ var _a;
100
+ const { error: settingsError, revision, studioRuntimeConfig } = (0, SettingsContext_1.useSettings)();
101
+ const [settings, setSettings] = (0, react_1.useState)(initialSettings);
102
+ const [committedNumberSettings, setCommittedNumberSettings] = (0, react_1.useState)({ maxTimelineTracks: null, numberOfSharedAudioTags: null });
103
+ const [editedSetters, setEditedSetters] = (0, react_1.useState)(() => new Set());
104
+ const [syncedRevision, setSyncedRevision] = (0, react_1.useState)(-1);
105
+ const [error, setError] = (0, react_1.useState)(null);
106
+ (0, react_1.useEffect)(() => {
107
+ var _a, _b;
108
+ var _c, _d, _e;
109
+ if (studioRuntimeConfig === null) {
110
+ return;
111
+ }
112
+ setSettings((_c = studioRuntimeConfig.configFileStudioSettings) !== null && _c !== void 0 ? _c : initialSettings);
113
+ setCommittedNumberSettings({
114
+ maxTimelineTracks: (_d = (_a = studioRuntimeConfig.configFileStudioSettings) === null || _a === void 0 ? void 0 : _a.maxTimelineTracks) !== null && _d !== void 0 ? _d : null,
115
+ numberOfSharedAudioTags: (_e = (_b = studioRuntimeConfig.configFileStudioSettings) === null || _b === void 0 ? void 0 : _b.numberOfSharedAudioTags) !== null && _e !== void 0 ? _e : null,
116
+ });
117
+ setEditedSetters(new Set());
118
+ setSyncedRevision(revision);
119
+ setError(null);
120
+ }, [revision, studioRuntimeConfig]);
121
+ const changeSetting = (0, react_1.useCallback)((key, setter, value) => {
122
+ setSettings((current) => ({ ...current, [key]: value }));
123
+ setEditedSetters((current) => new Set(current).add(setter));
124
+ }, []);
125
+ const previewNumberSetting = (0, react_1.useCallback)((key, value) => {
126
+ setSettings((current) => ({ ...current, [key]: value }));
127
+ }, []);
128
+ const commitNumberSetting = (0, react_1.useCallback)((key, setter, value) => {
129
+ setSettings((current) => ({ ...current, [key]: value }));
130
+ setCommittedNumberSettings((current) => ({ ...current, [key]: value }));
131
+ setEditedSetters((current) => new Set(current).add(setter));
132
+ }, []);
133
+ const updates = (0, react_1.useMemo)(() => {
134
+ const update = (setter, value) => value === null ? { setter, type: 'delete' } : { setter, type: 'set', value };
135
+ const updatesForEditedSetters = [
136
+ update('setAskAIEnabled', settings.askAIEnabled),
137
+ update('setEnableCrossSiteIsolation', settings.enableCrossSiteIsolation),
138
+ update('setBeepOnFinish', settings.beepOnFinish),
139
+ update('setMaxTimelineTracks', committedNumberSettings.maxTimelineTracks),
140
+ update('setAudioLatencyHint', settings.audioLatencyHint),
141
+ update('setNumberOfSharedAudioTags', committedNumberSettings.numberOfSharedAudioTags),
142
+ update('setRspack', settings.rspack),
143
+ update('setKeyboardShortcutsEnabled', settings.keyboardShortcutsEnabled),
144
+ update('setInteractivityEnabled', settings.interactivityEnabled),
145
+ update('setLogLevel', settings.logLevel),
146
+ ].filter((item) => editedSetters.has(item.setter));
147
+ if (editedSetters.has('setRspack')) {
148
+ updatesForEditedSetters.push({
149
+ setter: 'setExperimentalRspackEnabled',
150
+ type: 'delete',
151
+ });
152
+ }
153
+ if (editedSetters.has('setLogLevel')) {
154
+ updatesForEditedSetters.push({ setter: 'setLevel', type: 'delete' });
155
+ }
156
+ return updatesForEditedSetters;
157
+ }, [committedNumberSettings, editedSetters, settings]);
158
+ const ready = studioRuntimeConfig !== null && syncedRevision === revision;
159
+ (0, use_auto_save_config_1.useAutoSaveConfig)({
160
+ enabled: ready,
161
+ onError: setError,
162
+ ready,
163
+ syncRevision: syncedRevision,
164
+ updates,
165
+ });
166
+ if (studioRuntimeConfig === null) {
167
+ return null;
168
+ }
169
+ return (jsx_runtime_1.jsxs("div", { style: container, children: [
170
+ jsx_runtime_1.jsx("p", { style: dividerLabel, children: "Interface" }), jsx_runtime_1.jsx(ConfigSelect, { defaultLabel: "Enabled", name: "Ask AI enabled", onChange: (value) => changeSetting('askAIEnabled', 'setAskAIEnabled', value), options: booleanOptions, value: settings.askAIEnabled }), jsx_runtime_1.jsx(ConfigSelect, { defaultLabel: "Enabled", name: "Keyboard shortcuts enabled", onChange: (value) => changeSetting('keyboardShortcutsEnabled', 'setKeyboardShortcutsEnabled', value), options: booleanOptions, value: settings.keyboardShortcutsEnabled }), jsx_runtime_1.jsx(ConfigSelect, { defaultLabel: "Enabled", name: "Interactivity enabled", onChange: (value) => changeSetting('interactivityEnabled', 'setInteractivityEnabled', value), options: booleanOptions, value: settings.interactivityEnabled }), jsx_runtime_1.jsx(ConfigNumber, { defaultLabel: "Unlimited", defaultValue: studio_shared_1.DEFAULT_TIMELINE_TRACKS, name: "Max timeline tracks", onChange: (value) => previewNumberSetting('maxTimelineTracks', value), onChangeEnd: (value) => commitNumberSetting('maxTimelineTracks', 'setMaxTimelineTracks', value), value: settings.maxTimelineTracks }), jsx_runtime_1.jsx(RenderModalHr_1.RenderModalHr, {}), jsx_runtime_1.jsx("p", { style: dividerLabel, children: "Audio" }), jsx_runtime_1.jsx(ConfigSelect, { defaultLabel: "Playback", name: "Audio latency hint", onChange: (value) => changeSetting('audioLatencyHint', 'setAudioLatencyHint', value), options: [
171
+ { label: 'Interactive', value: 'interactive' },
172
+ { label: 'Balanced', value: 'balanced' },
173
+ { label: 'Playback', value: 'playback' },
174
+ ], value: settings.audioLatencyHint }), jsx_runtime_1.jsx(ConfigNumber, { defaultValue: 0, name: "Number of shared audio tags", onChange: (value) => previewNumberSetting('numberOfSharedAudioTags', value), onChangeEnd: (value) => commitNumberSetting('numberOfSharedAudioTags', 'setNumberOfSharedAudioTags', value), value: settings.numberOfSharedAudioTags }), jsx_runtime_1.jsx(ConfigSelect, { defaultLabel: "Disabled", name: "Beep on finish", onChange: (value) => changeSetting('beepOnFinish', 'setBeepOnFinish', value), options: booleanOptions, value: settings.beepOnFinish }), jsx_runtime_1.jsx(RenderModalHr_1.RenderModalHr, {}), jsx_runtime_1.jsx("p", { style: dividerLabel, children: "Development" }), jsx_runtime_1.jsx(ConfigSelect, { defaultLabel: "Webpack", name: "Bundler", onChange: (value) => changeSetting('rspack', 'setRspack', value), options: [
175
+ { label: 'Rspack', value: true },
176
+ { label: 'Webpack', value: false },
177
+ ], value: settings.rspack }), jsx_runtime_1.jsx(ConfigSelect, { defaultLabel: "Disabled", name: "Cross-site isolation", onChange: (value) => changeSetting('enableCrossSiteIsolation', 'setEnableCrossSiteIsolation', value), options: booleanOptions, value: settings.enableCrossSiteIsolation }), jsx_runtime_1.jsx(ConfigSelect, { defaultLabel: "Info", name: "Log level", onChange: (value) => changeSetting('logLevel', 'setLogLevel', value), options: client_1.BrowserSafeApis.logLevels.map((value) => ({
178
+ label: value[0].toUpperCase() + value.slice(1),
179
+ value,
180
+ })), value: settings.logLevel }), (error !== null && error !== void 0 ? error : settingsError) ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
181
+ jsx_runtime_1.jsx(layout_1.Spacing, { y: 1, block: true }), jsx_runtime_1.jsx("div", { style: { paddingLeft: 16, paddingRight: 16 }, children: jsx_runtime_1.jsx(ValidationMessage_1.ValidationMessage, { align: "flex-start", message: (_a = error !== null && error !== void 0 ? error : settingsError) !== null && _a !== void 0 ? _a : '', type: "error" }) })
182
+ ] })) : null, jsx_runtime_1.jsx(layout_1.Spacing, { y: 2, block: true })
183
+ ] }));
184
+ };
185
+ exports.StudioSettings = StudioSettings;
@@ -26,7 +26,7 @@ const centerContainer = {
26
26
  };
27
27
  const LoopedIndicator = () => {
28
28
  return (jsx_runtime_1.jsxs("div", { style: width, children: [
29
- jsx_runtime_1.jsx(remotion_1.AbsoluteFill, { style: centerContainer, children: jsx_runtime_1.jsx("div", { style: verticalLine }) }), jsx_runtime_1.jsx(remotion_1.AbsoluteFill, { style: centerContainer, children: jsx_runtime_1.jsx(Icon, {}) })
29
+ jsx_runtime_1.jsx(remotion_1.Internals.AbsoluteFillElement, { style: centerContainer, children: jsx_runtime_1.jsx("div", { style: verticalLine }) }), jsx_runtime_1.jsx(remotion_1.Internals.AbsoluteFillElement, { style: centerContainer, children: jsx_runtime_1.jsx(Icon, {}) })
30
30
  ] }));
31
31
  };
32
32
  exports.LoopedIndicator = LoopedIndicator;
@@ -1,4 +1,7 @@
1
1
  import React from 'react';
2
2
  export declare const LoopedTimelineIndicator: React.FC<{
3
3
  readonly loops: number;
4
+ readonly fullWidth: number;
5
+ readonly visibleOffset: number;
6
+ readonly visibleWidth: number;
4
7
  }>;
@@ -1,24 +1,32 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.LoopedTimelineIndicator = void 0;
7
4
  const jsx_runtime_1 = require("react/jsx-runtime");
8
- const react_1 = __importDefault(require("react"));
9
5
  const remotion_1 = require("remotion");
10
- const layout_1 = require("../layout");
11
6
  const LoopedIndicator_1 = require("./LoopedIndicator");
12
7
  const row = {
13
- flexDirection: 'row',
8
+ overflow: 'hidden',
14
9
  };
15
- const LoopedTimelineIndicator = ({ loops }) => {
16
- const leftOver = loops % 1;
17
- return (jsx_runtime_1.jsxs(remotion_1.AbsoluteFill, { style: row, children: [new Array(Math.floor(loops)).fill(true).map((_l, i) => {
18
- return (jsx_runtime_1.jsxs(react_1.default.Fragment
19
- // eslint-disable-next-line
20
- , { children: [
21
- jsx_runtime_1.jsx(layout_1.Flex, {}), i === loops - 1 ? null : jsx_runtime_1.jsx(LoopedIndicator_1.LoopedIndicator, {})] }, i));
22
- }), leftOver > 0 ? jsx_runtime_1.jsx("div", { style: { flex: leftOver } }) : null] }));
10
+ const LoopedTimelineIndicator = ({ loops, fullWidth, visibleOffset, visibleWidth }) => {
11
+ if (loops <= 1 || fullWidth <= 0 || visibleWidth <= 0) {
12
+ return null;
13
+ }
14
+ const loopWidth = fullWidth / loops;
15
+ const lastBoundaryIndex = Math.ceil(loops) - 1;
16
+ const firstVisibleBoundaryIndex = Math.max(1, Math.floor(visibleOffset / loopWidth));
17
+ const lastVisibleBoundaryIndex = Math.min(lastBoundaryIndex, Math.ceil((visibleOffset + visibleWidth) / loopWidth));
18
+ const visibleBoundaryCount = Math.max(0, lastVisibleBoundaryIndex - firstVisibleBoundaryIndex + 1);
19
+ const boundaries = new Array(visibleBoundaryCount)
20
+ .fill(true)
21
+ .map((_, index) => (firstVisibleBoundaryIndex + index) * loopWidth);
22
+ return (jsx_runtime_1.jsx(remotion_1.Internals.AbsoluteFillElement, { style: row, children: boundaries.map((boundary) => {
23
+ return (jsx_runtime_1.jsx("div", { style: {
24
+ position: 'absolute',
25
+ display: 'flex',
26
+ left: boundary - visibleOffset,
27
+ top: 0,
28
+ bottom: 0,
29
+ }, children: jsx_runtime_1.jsx(LoopedIndicator_1.LoopedIndicator, {}) }, boundary));
30
+ }) }));
23
31
  };
24
32
  exports.LoopedTimelineIndicator = LoopedTimelineIndicator;
@@ -75,6 +75,7 @@ const TimelineSelection_1 = require("./TimelineSelection");
75
75
  const TimelineSlider_1 = require("./TimelineSlider");
76
76
  const TimelineTimeIndicators_1 = require("./TimelineTimeIndicators");
77
77
  const TimelineTracks_1 = require("./TimelineTracks");
78
+ const TimelineVirtualization_1 = require("./TimelineVirtualization");
78
79
  const TimelineWidthProvider_1 = require("./TimelineWidthProvider");
79
80
  const use_resolved_stack_1 = require("./use-resolved-stack");
80
81
  const use_timeline_asset_drop_1 = require("./use-timeline-asset-drop");
@@ -329,7 +330,7 @@ const TimelineInner = () => {
329
330
  }, [filtered]);
330
331
  const maxTimelineTracks = (0, studio_runtime_config_1.getStudioMaxTimelineTracks)();
331
332
  const shown = (0, react_1.useMemo)(() => {
332
- return collapsed.length > maxTimelineTracks
333
+ return maxTimelineTracks !== null && collapsed.length > maxTimelineTracks
333
334
  ? collapsed.slice(0, maxTimelineTracks)
334
335
  : collapsed;
335
336
  }, [collapsed, maxTimelineTracks]);
@@ -339,14 +340,15 @@ const TimelineInner = () => {
339
340
  return null;
340
341
  }
341
342
  return (jsx_runtime_1.jsx(SubscribeToNodePaths_1.SubscribeToNodePaths, { overrideId: sequence.controls.overrideId, componentIdentity: sequence.controls.componentIdentity, schema: sequence.controls.schema, getStack: sequence.getStack, effects: sequence.effects }, sequence.id));
342
- }), (0, interactivity_enabled_1.isStudioInteractivityEnabled)() ? jsx_runtime_1.jsx(SequencePropsObserver_1.SequencePropsObserver, {}) : null, jsx_runtime_1.jsx(TimelineKeyframeTracksContext_1.TimelineKeyframeTracksProvider, { tracks: filtered, children: jsx_runtime_1.jsxs(TimelineSelection_1.TimelineSelectableItemsProvider, { timeline: shown, children: [(0, interactivity_enabled_1.isStudioInteractivityEnabled)() ? (jsx_runtime_1.jsx(TimelineSelection_1.TimelineSelectAllKeybindings, { timeline: shown })) : null, jsx_runtime_1.jsx(TimelineHeightContainer_1.TimelineHeightContainer, { shown: shown, hasBeenCut: hasBeenCut, isStill: isStill, children: isStill ? (jsx_runtime_1.jsx(TimelineList_1.TimelineList, { timeline: shown, showTimePadding: false })) : (jsx_runtime_1.jsxs(TimelineWidthProvider_1.TimelineWidthProvider, { children: [
343
- jsx_runtime_1.jsx(TimelinePinchZoom_1.TimelinePinchZoom, {}), jsx_runtime_1.jsxs(SplitterContainer_1.SplitterContainer, { orientation: "vertical", defaultFlex: 0.2, id: "names-to-timeline", maxFlex: 0.5, minFlex: 0.15, maxFlexerSize: null, minFlexerSize: MIN_TIMELINE_LABELS_WIDTH, maxAntiFlexerSize: null, minAntiFlexerSize: null, children: [
344
- jsx_runtime_1.jsx(SplitterElement_1.SplitterElement, { type: "flexer", sticky: jsx_runtime_1.jsx(TimelineTimeIndicators_1.TimelineTimePlaceholders, {}), children: jsx_runtime_1.jsx(TimelineList_1.TimelineList, { timeline: shown, showTimePadding: true }) }), jsx_runtime_1.jsx(SplitterHandle_1.SplitterHandle, { onCollapse: noop, allowToCollapse: "none" }), jsx_runtime_1.jsx(SplitterElement_1.SplitterElement, { type: "anti-flexer", sticky: null, children: jsx_runtime_1.jsxs(TimelineScrollable_1.TimelineScrollable, { children: [
345
- jsx_runtime_1.jsx(TimelineTracks_1.TimelineTracks, { timeline: shown, hasBeenCut: hasBeenCut }), jsx_runtime_1.jsx(TimelinePlayCursorSyncer_1.TimelinePlayCursorSyncer, {}), jsx_runtime_1.jsx(TimelineInOutPointer_1.TimelineInOutPointer, {}), jsx_runtime_1.jsx(TimelineTimeIndicators_1.TimelineTimeIndicators, {}), jsx_runtime_1.jsx(TimelineDragHandler_1.TimelineDragHandler, {}), (0, interactivity_enabled_1.isStudioInteractivityEnabled)() ? (jsx_runtime_1.jsx(TimelineInOutDragHandler_1.TimelineInOutDragHandler, {})) : null, jsx_runtime_1.jsx(TimelineSlider_1.TimelineSlider, {})
346
- ] }) })
347
- ] })
348
- ] })) })
349
- ] }) })
343
+ }), (0, interactivity_enabled_1.isStudioInteractivityEnabled)() ? jsx_runtime_1.jsx(SequencePropsObserver_1.SequencePropsObserver, {}) : null, jsx_runtime_1.jsx(TimelineKeyframeTracksContext_1.TimelineKeyframeTracksProvider, { tracks: filtered, children: jsx_runtime_1.jsx(TimelineSelection_1.TimelineSelectableItemsProvider, { timeline: shown, children: jsx_runtime_1.jsxs(TimelineVirtualization_1.TimelineVirtualizationProvider, { hasBeenCut: hasBeenCut, isStill: isStill, timeline: shown, children: [(0, interactivity_enabled_1.isStudioInteractivityEnabled)() ? (jsx_runtime_1.jsx(TimelineSelection_1.TimelineSelectAllKeybindings, { timeline: shown })) : null, jsx_runtime_1.jsx(TimelineHeightContainer_1.TimelineHeightContainer, { children: isStill ? (jsx_runtime_1.jsx(TimelineList_1.TimelineList, {})) : (jsx_runtime_1.jsxs(TimelineWidthProvider_1.TimelineWidthProvider, { children: [
344
+ jsx_runtime_1.jsx(TimelinePinchZoom_1.TimelinePinchZoom, {}), jsx_runtime_1.jsxs(SplitterContainer_1.SplitterContainer, { orientation: "vertical", defaultFlex: 0.2, id: "names-to-timeline", maxFlex: 0.5, minFlex: 0.15, maxFlexerSize: null, minFlexerSize: MIN_TIMELINE_LABELS_WIDTH, maxAntiFlexerSize: null, minAntiFlexerSize: null, children: [
345
+ jsx_runtime_1.jsx(SplitterElement_1.SplitterElement, { type: "flexer", sticky: jsx_runtime_1.jsx(TimelineTimeIndicators_1.TimelineTimePlaceholders, {}), children: jsx_runtime_1.jsx(TimelineList_1.TimelineList, {}) }), jsx_runtime_1.jsx(SplitterHandle_1.SplitterHandle, { onCollapse: noop, allowToCollapse: "none" }), jsx_runtime_1.jsx(SplitterElement_1.SplitterElement, { type: "anti-flexer", sticky: jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
346
+ jsx_runtime_1.jsx(TimelineTimeIndicators_1.TimelineTimeIndicators, {}), jsx_runtime_1.jsx(TimelineSlider_1.TimelineSlider, {})
347
+ ] }), children: jsx_runtime_1.jsxs(TimelineScrollable_1.TimelineScrollable, { children: [
348
+ jsx_runtime_1.jsx(TimelineTracks_1.TimelineTracks, { hasBeenCut: hasBeenCut }), jsx_runtime_1.jsx(TimelinePlayCursorSyncer_1.TimelinePlayCursorSyncer, {}), jsx_runtime_1.jsx(TimelineInOutPointer_1.TimelineInOutPointer, {}), jsx_runtime_1.jsx(TimelineDragHandler_1.TimelineDragHandler, {}), (0, interactivity_enabled_1.isStudioInteractivityEnabled)() ? (jsx_runtime_1.jsx(TimelineInOutDragHandler_1.TimelineInOutDragHandler, {})) : null] }) })
349
+ ] })
350
+ ] })) })
351
+ ] }) }) })
350
352
  ] }));
351
353
  };
352
354
  exports.Timeline = react_1.default.memo(TimelineInner);
@@ -155,6 +155,7 @@ const ItemEditor = ({ field, arrayField, items, index, onSave, onDragValueChange
155
155
  }, [arrayField, fallback, field, index]);
156
156
  const propStatus = (0, react_1.useMemo)(() => ({
157
157
  status: 'static',
158
+ keyframeDisplayOffsetAdjustment: null,
158
159
  codeValue: value,
159
160
  }), [value]);
160
161
  const onSaveItem = (0, react_1.useCallback)((next) => onSave(replaceAtIndex(items, index, next)), [index, items, onSave]);
@@ -1,8 +1,8 @@
1
1
  import React from 'react';
2
2
  import { type CanUpdateSequencePropStatusStatic } from 'remotion';
3
3
  import type { SchemaFieldInfo, TimelineFieldOnDragValueChange, TimelineFieldOnSave } from '../../helpers/timeline-layout';
4
- import { type InspectorInlineActionProps } from '../InspectorPanel/common';
5
- export type InspectorSourceAction = Omit<InspectorInlineActionProps, 'variant'>;
4
+ import { type InspectorQuickActionProps } from '../InspectorPanel/common';
5
+ export type InspectorSourceAction = Omit<InspectorQuickActionProps, 'variant'>;
6
6
  type AssetSelectionContextValue = {
7
7
  readonly initialQuery: string;
8
8
  readonly getSourceAction: (src: string) => InspectorSourceAction | null;
@@ -100,7 +100,7 @@ const TimelineAssetField = ({ field, effectiveValue, propStatus, onSave, onDragV
100
100
  if (inlineSourceAction === null) {
101
101
  return action;
102
102
  }
103
- return (jsx_runtime_1.jsx(common_1.InspectorInlineAction, { ...inlineSourceAction, size: "compact", variant: {
103
+ return (jsx_runtime_1.jsx(common_1.InspectorQuickAction, { ...inlineSourceAction, size: "compact", variant: {
104
104
  type: 'segmented',
105
105
  trailing: {
106
106
  disabled: window.remotion_isReadOnlyStudio,