@remotion/studio 4.0.519 → 4.0.521

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/dist/api/shut-down-studio.d.ts +6 -0
  2. package/dist/api/shut-down-studio.js +23 -0
  3. package/dist/api/visual-control.js +2 -2
  4. package/dist/components/AudioWaveform.js +16 -7
  5. package/dist/components/Canvas.js +114 -48
  6. package/dist/components/CaptionInspector.d.ts +1 -0
  7. package/dist/components/CaptionInspector.js +43 -2
  8. package/dist/components/CaptionTextEditor.js +1 -1
  9. package/dist/components/CompositionSelector.js +41 -34
  10. package/dist/components/CompositionSelectorItem.d.ts +7 -0
  11. package/dist/components/CompositionSelectorItem.js +344 -73
  12. package/dist/components/CurrentCompositionSideEffects.js +5 -0
  13. package/dist/components/ElementInstallConfirmation.d.ts +2 -23
  14. package/dist/components/ElementInstallConfirmation.js +89 -65
  15. package/dist/components/ElementLibraryModal.js +3 -1
  16. package/dist/components/FpsCounter.js +1 -1
  17. package/dist/components/FramePersistor.js +1 -1
  18. package/dist/components/InlineCaptionInspector.js +37 -1
  19. package/dist/components/InspectorPanel/ElementLibraryButton.js +3 -18
  20. package/dist/components/InspectorPanel/SequenceSelectionInspector.js +4 -3
  21. package/dist/components/InspectorPanel/use-composition-actions.js +5 -8
  22. package/dist/components/InspectorSequenceSection.js +1 -4
  23. package/dist/components/Menu/MenuSubItem.js +1 -1
  24. package/dist/components/ModalContainer.d.ts +1 -0
  25. package/dist/components/ModalContainer.js +2 -2
  26. package/dist/components/ModalHeader.js +5 -1
  27. package/dist/components/Modals.js +1 -1
  28. package/dist/components/NewComposition/NewComposition.js +2 -2
  29. package/dist/components/PlayPause.js +2 -13
  30. package/dist/components/PreviewToolbar.js +1 -1
  31. package/dist/components/QuickSwitcher/QuickSwitcherContent.js +29 -15
  32. package/dist/components/QuickSwitcher/QuickSwitcherResult.d.ts +14 -1
  33. package/dist/components/QuickSwitcher/QuickSwitcherResult.js +64 -9
  34. package/dist/components/QuickSwitcher/asset-search.d.ts +0 -1
  35. package/dist/components/QuickSwitcher/asset-search.js +1 -16
  36. package/dist/components/QuickSwitcher/composition-search.d.ts +16 -0
  37. package/dist/components/QuickSwitcher/composition-search.js +136 -0
  38. package/dist/components/RenderButton.js +2 -2
  39. package/dist/components/RenderModal/RenderStatusModal.js +7 -1
  40. package/dist/components/RenderModal/ServerRenderModal.js +1 -1
  41. package/dist/components/RenderModal/WebRenderModal.js +1 -1
  42. package/dist/components/RenderQueue/ClientRenderQueueProcessor.js +1 -1
  43. package/dist/components/ResetZoomButton.js +17 -2
  44. package/dist/components/SelectedOutlineElement.js +10 -30
  45. package/dist/components/SettingsModal.js +8 -5
  46. package/dist/components/TimeValue.js +36 -7
  47. package/dist/components/Timeline/Timeline.d.ts +1 -1
  48. package/dist/components/Timeline/Timeline.js +33 -20
  49. package/dist/components/Timeline/TimelineAssetField.d.ts +0 -1
  50. package/dist/components/Timeline/TimelineAssetField.js +17 -9
  51. package/dist/components/Timeline/TimelineCollapseToggle.js +1 -1
  52. package/dist/components/Timeline/TimelineDeleteKeybindings.js +5 -90
  53. package/dist/components/Timeline/TimelineDragHandler.js +18 -8
  54. package/dist/components/Timeline/TimelineFontWeightField.d.ts +11 -0
  55. package/dist/components/Timeline/TimelineFontWeightField.js +65 -0
  56. package/dist/components/Timeline/TimelineInOutDragHandler.js +2 -3
  57. package/dist/components/Timeline/TimelineLayerChildren.d.ts +21 -0
  58. package/dist/components/Timeline/TimelineLayerChildren.js +129 -0
  59. package/dist/components/Timeline/TimelineNumberField.js +13 -5
  60. package/dist/components/Timeline/TimelinePinchZoom.js +14 -4
  61. package/dist/components/Timeline/TimelinePlayCursorSyncer.js +8 -4
  62. package/dist/components/Timeline/TimelinePrimitiveFieldValue.js +4 -0
  63. package/dist/components/Timeline/TimelineSequence.js +54 -73
  64. package/dist/components/Timeline/TimelineSequenceItem.js +16 -36
  65. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +22 -10
  66. package/dist/components/Timeline/TimelineSlider.js +2 -2
  67. package/dist/components/Timeline/TimelineTickFormatProvider.d.ts +8 -0
  68. package/dist/components/Timeline/TimelineTickFormatProvider.js +16 -0
  69. package/dist/components/Timeline/TimelineTimeIndicators.js +7 -3
  70. package/dist/components/Timeline/TimelineVideoInfo.js +7 -3
  71. package/dist/components/Timeline/TimelineWidthProvider.js +15 -8
  72. package/dist/components/Timeline/TimelineZoomControls.js +25 -8
  73. package/dist/components/Timeline/delete-selected-timeline-item.js +2 -2
  74. package/dist/components/Timeline/timeline-field-display-utils.js +1 -0
  75. package/dist/components/Timeline/timeline-scroll-logic.d.ts +1 -0
  76. package/dist/components/Timeline/timeline-scroll-logic.js +21 -17
  77. package/dist/components/Timeline/use-delete-timeline-items.d.ts +1 -0
  78. package/dist/components/Timeline/use-delete-timeline-items.js +118 -0
  79. package/dist/components/Timeline/use-timeline-asset-drop.js +8 -14
  80. package/dist/components/UpdateStatusContext.d.ts +5 -0
  81. package/dist/components/UpdateStatusContext.js +53 -2
  82. package/dist/components/UpdatesSettings.js +25 -4
  83. package/dist/components/WebMcp.js +87 -8
  84. package/dist/components/ZoomPersistor.js +2 -2
  85. package/dist/components/composition-drag-data.d.ts +36 -0
  86. package/dist/components/composition-drag-data.js +232 -0
  87. package/dist/components/composition-selector-drag-data.d.ts +27 -0
  88. package/dist/components/composition-selector-drag-data.js +80 -0
  89. package/dist/components/drop-handler-data.d.ts +2 -1
  90. package/dist/components/drop-handler-data.js +6 -4
  91. package/dist/components/effect-drag-and-drop.d.ts +2 -5
  92. package/dist/components/handle-drop.js +6 -2
  93. package/dist/components/import-assets.d.ts +7 -14
  94. package/dist/components/import-assets.js +11 -1
  95. package/dist/components/parse-caption-file.d.ts +5 -0
  96. package/dist/components/parse-caption-file.js +63 -0
  97. package/dist/error-overlay/current-error.d.ts +13 -0
  98. package/dist/error-overlay/current-error.js +21 -0
  99. package/dist/error-overlay/remotion-overlay/ErrorLoader.js +5 -1
  100. package/dist/esm/chunk-emw4k5b0.js +99527 -0
  101. package/dist/esm/{chunk-1fkq5bfq.js → chunk-vkrvnx2h.js} +20116 -16283
  102. package/dist/esm/index.mjs +27 -9
  103. package/dist/esm/internals.mjs +17408 -13426
  104. package/dist/esm/previewEntry.mjs +17285 -13216
  105. package/dist/esm/renderEntry.mjs +1 -1
  106. package/dist/helpers/create-folder-tree.js +2 -5
  107. package/dist/helpers/document-title.d.ts +2 -0
  108. package/dist/helpers/document-title.js +14 -3
  109. package/dist/helpers/get-preview-file-type.js +22 -3
  110. package/dist/helpers/get-timeline-max-zoom.d.ts +34 -28
  111. package/dist/helpers/get-timeline-max-zoom.js +46 -29
  112. package/dist/helpers/inserted-element-selection.d.ts +2 -1
  113. package/dist/helpers/install-fiber-sequence-order-observer.d.ts +37 -0
  114. package/dist/helpers/install-fiber-sequence-order-observer.js +109 -0
  115. package/dist/helpers/open-in-editor.js +2 -1
  116. package/dist/helpers/use-menu-structure.js +2 -2
  117. package/dist/helpers/use-runtime-values.d.ts +1 -1
  118. package/dist/helpers/use-runtime-values.js +5 -4
  119. package/dist/helpers/use-sync-external-store.d.ts +3 -0
  120. package/dist/helpers/use-sync-external-store.js +5 -0
  121. package/dist/index.d.ts +1 -0
  122. package/dist/index.js +3 -1
  123. package/dist/previewEntry.js +2 -0
  124. package/dist/state/modals.d.ts +16 -2
  125. package/dist/state/timeline-sequence-hover.js +3 -2
  126. package/dist/state/timeline-zoom.d.ts +0 -1
  127. package/dist/state/timeline-zoom.js +13 -6
  128. package/package.json +17 -17
  129. package/dist/helpers/sort-by-nonce-history.d.ts +0 -1
  130. package/dist/helpers/sort-by-nonce-history.js +0 -6
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useDeleteTimelineItems = void 0;
4
+ const studio_shared_1 = require("@remotion/studio-shared");
5
+ const react_1 = require("react");
6
+ const remotion_1 = require("remotion");
7
+ const client_id_1 = require("../../helpers/client-id");
8
+ const editor_guides_1 = require("../../state/editor-guides");
9
+ const ConfirmationDialog_1 = require("../ConfirmationDialog");
10
+ const delete_selected_timeline_item_1 = require("./delete-selected-timeline-item");
11
+ const imperative_state_1 = require("./imperative-state");
12
+ const reset_selected_timeline_props_1 = require("./reset-selected-timeline-props");
13
+ const TimelineSelection_1 = require("./TimelineSelection");
14
+ const update_selected_easing_1 = require("./update-selected-easing");
15
+ const useDeleteTimelineItems = () => {
16
+ const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
17
+ const sequencesRef = (0, react_1.useContext)(remotion_1.Internals.SequenceManagerRefContext);
18
+ const { overrideIdToNodePathMappings } = (0, react_1.useContext)(remotion_1.Internals.OverrideIdsToNodePathsGettersContext);
19
+ const propStatusesRef = (0, react_1.useContext)(remotion_1.Internals.VisualModePropStatusesRefContext);
20
+ const { setPropStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
21
+ const { setGuidesList } = (0, react_1.useContext)(editor_guides_1.EditorShowGuidesContext);
22
+ const currentSelection = (0, TimelineSelection_1.useCurrentTimelineSelectionStateAsRef)();
23
+ const confirm = (0, ConfirmationDialog_1.useConfirmationDialog)();
24
+ return (0, react_1.useCallback)((selectedItemsOverride) => {
25
+ if (previewServerState.type !== 'connected') {
26
+ return;
27
+ }
28
+ const { clientId } = previewServerState;
29
+ const { selectedItems: currentSelectedItems, clearSelection, selectItems, } = currentSelection.current;
30
+ const selectedItems = selectedItemsOverride !== null && selectedItemsOverride !== void 0 ? selectedItemsOverride : currentSelectedItems;
31
+ const sequences = sequencesRef.current;
32
+ const propStatuses = propStatusesRef.current;
33
+ const timelinePosition = (0, imperative_state_1.getCurrentFrame)();
34
+ if (selectedItems.length === 0) {
35
+ return;
36
+ }
37
+ const selectedGuide = selectedItems.find((item) => item.type === 'guide');
38
+ if (selectedGuide) {
39
+ setGuidesList((prevGuides) => {
40
+ const newGuides = prevGuides.filter((guide) => guide.id !== selectedGuide.guideId);
41
+ (0, editor_guides_1.persistGuidesList)(newGuides);
42
+ return newGuides;
43
+ });
44
+ clearSelection();
45
+ return;
46
+ }
47
+ const deletePromise = (0, delete_selected_timeline_item_1.deleteSelectedTimelineItems)({
48
+ selections: selectedItems,
49
+ sequences,
50
+ overrideIdsToNodePaths: overrideIdToNodePathMappings,
51
+ setPropStatuses,
52
+ clientId,
53
+ confirm,
54
+ propStatuses,
55
+ timelinePosition,
56
+ });
57
+ if (deletePromise !== null) {
58
+ deletePromise
59
+ .then((deleted) => {
60
+ if (!deleted) {
61
+ return;
62
+ }
63
+ const nextSelection = (0, delete_selected_timeline_item_1.getTimelineSelectionAfterDeletingItems)({
64
+ selections: selectedItems,
65
+ sequences,
66
+ overrideIdsToNodePaths: overrideIdToNodePathMappings,
67
+ propStatuses,
68
+ timelinePosition,
69
+ });
70
+ if (nextSelection.length === 0) {
71
+ clearSelection();
72
+ }
73
+ else {
74
+ selectItems(nextSelection);
75
+ }
76
+ })
77
+ .catch(() => undefined);
78
+ return;
79
+ }
80
+ const easingSelections = (0, update_selected_easing_1.getEasingSelections)(selectedItems);
81
+ if (easingSelections.length === selectedItems.length) {
82
+ const resetEasingPromise = (0, update_selected_easing_1.updateSelectedTimelineEasings)({
83
+ selections: easingSelections,
84
+ sequences,
85
+ overrideIdsToNodePaths: overrideIdToNodePathMappings,
86
+ propStatuses,
87
+ setPropStatuses,
88
+ clientId,
89
+ easing: studio_shared_1.LINEAR_KEYFRAME_EASING,
90
+ });
91
+ if (resetEasingPromise !== null) {
92
+ resetEasingPromise.catch(() => undefined);
93
+ return;
94
+ }
95
+ }
96
+ const resetPromise = (0, reset_selected_timeline_props_1.resetSelectedTimelineProps)({
97
+ selections: selectedItems,
98
+ sequences,
99
+ overrideIdsToNodePaths: overrideIdToNodePathMappings,
100
+ propStatuses,
101
+ setPropStatuses,
102
+ clientId,
103
+ });
104
+ if (resetPromise !== null) {
105
+ resetPromise.catch(() => undefined);
106
+ }
107
+ }, [
108
+ confirm,
109
+ currentSelection,
110
+ overrideIdToNodePathMappings,
111
+ previewServerState,
112
+ propStatusesRef,
113
+ sequencesRef,
114
+ setGuidesList,
115
+ setPropStatuses,
116
+ ]);
117
+ };
118
+ exports.useDeleteTimelineItems = useDeleteTimelineItems;
@@ -17,15 +17,8 @@ const imperative_state_1 = require("./imperative-state");
17
17
  const timeline_refs_1 = require("./timeline-refs");
18
18
  const timeline_scroll_logic_1 = require("./timeline-scroll-logic");
19
19
  const use_resolved_stack_1 = require("./use-resolved-stack");
20
- const isEventInsideElement = (event, element) => {
21
- if (event.target instanceof Node && element.contains(event.target)) {
22
- return true;
23
- }
24
- const rect = element.getBoundingClientRect();
25
- return (event.clientX >= rect.left &&
26
- event.clientX <= rect.right &&
27
- event.clientY >= rect.top &&
28
- event.clientY <= rect.bottom);
20
+ const isEventTargetInsideElement = (event, element) => {
21
+ return event.target instanceof Node && element.contains(event.target);
29
22
  };
30
23
  const useTimelineAssetDrop = () => {
31
24
  var _a, _b;
@@ -60,13 +53,14 @@ const useTimelineAssetDrop = () => {
60
53
  return null;
61
54
  }
62
55
  const scrollable = timeline_refs_1.scrollableRef.current;
63
- return scrollable !== null && isEventInsideElement(event, scrollable)
56
+ return scrollable !== null &&
57
+ isEventTargetInsideElement(event, scrollable)
64
58
  ? (0, timeline_scroll_logic_1.getFrameFromTimelineDrop)({
65
59
  clientX: event.clientX,
66
60
  durationInFrames: videoConfig.durationInFrames,
67
61
  scrollLeft: scrollable.scrollLeft,
68
62
  timelineLeft: scrollable.getBoundingClientRect().left,
69
- timelineWidth: scrollable.scrollWidth,
63
+ timelineWidth: (0, timeline_scroll_logic_1.getTimelineContentWidth)(),
70
64
  })
71
65
  : (0, imperative_state_1.getCurrentFrame)();
72
66
  }, [videoConfig]);
@@ -76,7 +70,7 @@ const useTimelineAssetDrop = () => {
76
70
  if (timeline === null ||
77
71
  dataTransfer === null ||
78
72
  !(0, drop_handler_data_1.isSupportedDropEvent)(event) ||
79
- !isEventInsideElement(event, timeline)) {
73
+ !isEventTargetInsideElement(event, timeline)) {
80
74
  setAssetDropFrame(null);
81
75
  return;
82
76
  }
@@ -86,7 +80,7 @@ const useTimelineAssetDrop = () => {
86
80
  const scrollable = timeline_refs_1.scrollableRef.current;
87
81
  const shouldShowDropFrame = canInsertAsset &&
88
82
  scrollable !== null &&
89
- isEventInsideElement(event, scrollable);
83
+ isEventTargetInsideElement(event, scrollable);
90
84
  setAssetDropFrame(shouldShowDropFrame ? getDropFrame(event) : null);
91
85
  }, [canInsertAsset, getDropFrame]);
92
86
  const onAssetDrop = (0, react_1.useCallback)(async (event) => {
@@ -96,7 +90,7 @@ const useTimelineAssetDrop = () => {
96
90
  if (timeline === null ||
97
91
  dataTransfer === null ||
98
92
  !(0, drop_handler_data_1.isSupportedDropEvent)(event) ||
99
- !isEventInsideElement(event, timeline)) {
93
+ !isEventTargetInsideElement(event, timeline)) {
100
94
  return;
101
95
  }
102
96
  const localFiles = (0, drop_handler_data_1.isFileDragEvent)(event)
@@ -6,7 +6,12 @@ export type Bug = {
6
6
  link: string;
7
7
  versions: string[];
8
8
  };
9
+ type UpgradeState = 'idle' | 'upgrading' | 'upgraded' | 'shutting-down' | 'shutdown';
9
10
  type UpdateStatusContextValue = {
11
+ readonly upgradeState: UpgradeState;
12
+ readonly upgradeError: string | null;
13
+ readonly upgrade: (version: string) => Promise<void>;
14
+ readonly shutdown: () => Promise<void>;
10
15
  readonly error: string | null;
11
16
  readonly info: UpdateAvailableResponse | null;
12
17
  readonly knownBugs: Bug[] | null;
@@ -4,13 +4,56 @@ exports.useUpdateStatus = exports.UpdateStatusProvider = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const remotion_1 = require("remotion");
7
+ const shut_down_studio_1 = require("../api/shut-down-studio");
7
8
  const browser_studio_operations_1 = require("../helpers/browser-studio-operations");
8
9
  const can_show_updates_1 = require("../helpers/can-show-updates");
9
10
  const client_id_1 = require("../helpers/client-id");
11
+ const call_api_1 = require("./call-api");
10
12
  const actions_1 = require("./RenderQueue/actions");
11
13
  const UpdateStatusContext = (0, react_1.createContext)(null);
12
14
  const UpdateStatusProvider = ({ children }) => {
13
15
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
16
+ const [upgradeState, setUpgradeState] = (0, react_1.useState)('idle');
17
+ const [upgradeError, setUpgradeError] = (0, react_1.useState)(null);
18
+ const busy = (0, react_1.useRef)(false);
19
+ const upgrade = (0, react_1.useCallback)(async (version) => {
20
+ if (busy.current) {
21
+ return;
22
+ }
23
+ busy.current = true;
24
+ setUpgradeState('upgrading');
25
+ setUpgradeError(null);
26
+ try {
27
+ await (0, call_api_1.callApi)('/api/upgrade-remotion', { version });
28
+ setUpgradeState('upgraded');
29
+ }
30
+ catch (err) {
31
+ setUpgradeError(err.message);
32
+ setUpgradeState('idle');
33
+ }
34
+ finally {
35
+ busy.current = false;
36
+ }
37
+ }, []);
38
+ const shutdown = (0, react_1.useCallback)(async () => {
39
+ if (busy.current) {
40
+ return;
41
+ }
42
+ busy.current = true;
43
+ setUpgradeState('shutting-down');
44
+ setUpgradeError(null);
45
+ try {
46
+ await (0, shut_down_studio_1.shutDownStudio)();
47
+ setUpgradeState('shutdown');
48
+ }
49
+ catch (err) {
50
+ setUpgradeError(err.message);
51
+ setUpgradeState('upgraded');
52
+ }
53
+ finally {
54
+ busy.current = false;
55
+ }
56
+ }, []);
14
57
  const [info, setInfo] = (0, react_1.useState)(null);
15
58
  const [knownBugs, setKnownBugs] = (0, react_1.useState)(null);
16
59
  const [error, setError] = (0, react_1.useState)(null);
@@ -59,8 +102,16 @@ const UpdateStatusProvider = ({ children }) => {
59
102
  };
60
103
  }, [showUpdates]);
61
104
  const value = (0, react_1.useMemo)(() => {
62
- return { error, info, knownBugs };
63
- }, [error, info, knownBugs]);
105
+ return {
106
+ error,
107
+ info,
108
+ knownBugs,
109
+ upgradeState,
110
+ upgradeError,
111
+ upgrade,
112
+ shutdown,
113
+ };
114
+ }, [error, info, knownBugs, upgradeState, upgradeError, upgrade, shutdown]);
64
115
  return (jsx_runtime_1.jsx(UpdateStatusContext.Provider, { value: value, children: children }));
65
116
  };
66
117
  exports.UpdateStatusProvider = UpdateStatusProvider;
@@ -8,6 +8,7 @@ const copy_text_1 = require("../helpers/copy-text");
8
8
  const clipboard_1 = require("../icons/clipboard");
9
9
  const InlineAction_1 = require("./InlineAction");
10
10
  const KnownBugs_1 = require("./KnownBugs");
11
+ const ModalButton_1 = require("./ModalButton");
11
12
  const ValidationMessage_1 = require("./NewComposition/ValidationMessage");
12
13
  const NotificationCenter_1 = require("./Notifications/NotificationCenter");
13
14
  const actions_1 = require("./RenderQueue/actions");
@@ -86,6 +87,7 @@ const commands = {
86
87
  yarn: 'yarn remotion upgrade',
87
88
  pnpm: 'pnpm exec remotion upgrade',
88
89
  bun: 'bun remotion upgrade',
90
+ nub: 'nubx remotion upgrade',
89
91
  unknown: 'npx remotion upgrade',
90
92
  };
91
93
  const skillsUpdateCommand = 'npx remotion skills update';
@@ -170,7 +172,7 @@ const RenderedReleaseNotes = ({ release }) => {
170
172
  };
171
173
  const UpdatesSettings = () => {
172
174
  const { remotionSkillsInfo } = (0, SettingsContext_1.useSettings)();
173
- const { error, info, knownBugs } = (0, UpdateStatusContext_1.useUpdateStatus)();
175
+ const { error, info, knownBugs, upgradeState, upgradeError, upgrade, shutdown, } = (0, UpdateStatusContext_1.useUpdateStatus)();
174
176
  const [releaseNotes, setReleaseNotes] = (0, react_1.useState)(null);
175
177
  (0, react_1.useEffect)(() => {
176
178
  if (!(info === null || info === void 0 ? void 0 : info.updateAvailable)) {
@@ -222,6 +224,23 @@ const UpdatesSettings = () => {
222
224
  const renderCopyAction = (0, react_1.useCallback)((color) => {
223
225
  return jsx_runtime_1.jsx(clipboard_1.ClipboardIcon, { color: color, style: copyIcon });
224
226
  }, []);
227
+ const onUpgrade = (0, react_1.useCallback)(() => {
228
+ if (info) {
229
+ upgrade(info.latestVersion);
230
+ }
231
+ }, [info, upgrade]);
232
+ if (upgradeState !== 'idle') {
233
+ return (jsx_runtime_1.jsxs("div", { style: container, children: [
234
+ jsx_runtime_1.jsx("div", { style: title, children: upgradeState === 'upgrading'
235
+ ? 'Upgrading Remotion...'
236
+ : 'Remotion has been upgraded.' }), jsx_runtime_1.jsx("div", { style: text, children: upgradeState === 'upgrading'
237
+ ? 'This may take a few minutes. You can follow the progress in your terminal.'
238
+ : upgradeState === 'shutdown'
239
+ ? 'Studio is shutting down. Run your Studio start command again in the terminal to use the new version.'
240
+ : 'Restart Studio to use the new version. Shut down the server below, then run your Studio start command again in the terminal.' }), upgradeState === 'upgraded' || upgradeState === 'shutting-down' ? (jsx_runtime_1.jsx("div", { style: { marginTop: 12 }, children: jsx_runtime_1.jsx(ModalButton_1.ModalButton, { onClick: shutdown, disabled: upgradeState === 'shutting-down', children: upgradeState === 'shutting-down'
241
+ ? 'Shutting down...'
242
+ : 'Shut down Studio' }) })) : null, upgradeError ? (jsx_runtime_1.jsx(ValidationMessage_1.ValidationMessage, { message: upgradeError, type: "error", align: "flex-start" })) : null] }));
243
+ }
225
244
  if (info === null) {
226
245
  return (jsx_runtime_1.jsx("div", { style: container, children: error ? (jsx_runtime_1.jsx("div", { style: { paddingTop: 12 }, children: jsx_runtime_1.jsx(ValidationMessage_1.ValidationMessage, { message: 'Could not check for updates: ' + error, align: "flex-start", type: "error" }) })) : (jsx_runtime_1.jsx("div", { style: title, children: "Checking for updates..." })) }));
227
246
  }
@@ -235,9 +254,11 @@ const UpdatesSettings = () => {
235
254
  jsx_runtime_1.jsxs("div", { style: title, children: ["You", "'re", " up to date."] }), jsx_runtime_1.jsxs("div", { style: text, children: ["Remotion ", info.currentVersion, " and your Remotion Agent Skills are up to date."] })
236
255
  ] }));
237
256
  }
238
- return (jsx_runtime_1.jsxs("div", { style: container, children: [hasKnownBugs && info.updateAvailable ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
239
- jsx_runtime_1.jsxs("div", { style: title, children: ["The currently installed version ", info.currentVersion, " has the following known bugs:"] }), jsx_runtime_1.jsx(KnownBugs_1.KnownBugs, { bugs: knownBugs !== null && knownBugs !== void 0 ? knownBugs : [] }), jsx_runtime_1.jsx("div", { style: { height: '20px' } }), jsx_runtime_1.jsxs("div", { style: text, children: ["To update, run the following ", updateActionType, ":"] })
240
- ] })) : info.updateAvailable ? (jsx_runtime_1.jsxs("div", { style: titleBeforeCommand, children: ["A new Remotion update is available. Run the following", ' ', updateActionType, ":"] })) : (jsx_runtime_1.jsxs("div", { style: titleBeforeCommand, children: ["Your Remotion Agent Skills are out of date. Run the following", ' ', updateActionType, ":"] })), jsx_runtime_1.jsxs("div", { style: commandField, children: [
257
+ return (jsx_runtime_1.jsxs("div", { style: container, children: [info.updateAvailable && info.packageManager !== 'unknown' ? (jsx_runtime_1.jsxs("div", { style: { paddingTop: 12 }, children: [
258
+ jsx_runtime_1.jsxs(ModalButton_1.ModalButton, { onClick: onUpgrade, children: ["Upgrade to ", info.latestVersion] }), jsx_runtime_1.jsx("div", { style: { ...text, marginTop: 8 }, children: "You will need to restart Studio after upgrading." })
259
+ ] })) : null, upgradeError ? (jsx_runtime_1.jsx(ValidationMessage_1.ValidationMessage, { message: upgradeError, type: "error", align: "flex-start" })) : null, hasKnownBugs && info.updateAvailable ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
260
+ jsx_runtime_1.jsxs("div", { style: title, children: ["The currently installed version ", info.currentVersion, " has the following known bugs:"] }), jsx_runtime_1.jsx(KnownBugs_1.KnownBugs, { bugs: knownBugs !== null && knownBugs !== void 0 ? knownBugs : [] }), jsx_runtime_1.jsx("div", { style: { height: '20px' } }), jsx_runtime_1.jsxs("div", { style: text, children: ["Or run the following ", updateActionType, ":"] })
261
+ ] })) : info.updateAvailable ? (jsx_runtime_1.jsxs("div", { style: titleBeforeCommand, children: ["A new Remotion update is available. You can also run the following", ' ', updateActionType, ":"] })) : (jsx_runtime_1.jsxs("div", { style: titleBeforeCommand, children: ["Your Remotion Agent Skills are out of date. Run the following", ' ', updateActionType, ":"] })), jsx_runtime_1.jsxs("div", { style: commandField, children: [
241
262
  jsx_runtime_1.jsx("pre", { style: code, children: updateAction }), jsx_runtime_1.jsx(InlineAction_1.InlineAction, { variant: null, onClick: onClick, renderAction: renderCopyAction, title: "Copy command" })
242
263
  ] }), info.updateAvailable ? (jsx_runtime_1.jsxs("div", { style: text, children: ["This will update Remotion from ", info.currentVersion, " to", ' ', info.latestVersion, info.skillsUpdateAvailable
243
264
  ? ' and update your project Remotion Agent Skills.'
@@ -5,7 +5,10 @@ const react_1 = require("react");
5
5
  const remotion_1 = require("remotion");
6
6
  const pause_1 = require("../api/pause");
7
7
  const play_1 = require("../api/play");
8
+ const restart_studio_1 = require("../api/restart-studio");
8
9
  const seek_1 = require("../api/seek");
10
+ const shut_down_studio_1 = require("../api/shut-down-studio");
11
+ const current_error_1 = require("../error-overlay/current-error");
9
12
  const calculate_timeline_1 = require("../helpers/calculate-timeline");
10
13
  const create_folder_tree_1 = require("../helpers/create-folder-tree");
11
14
  const format_file_location_1 = require("../helpers/format-file-location");
@@ -21,6 +24,7 @@ const find_track_for_node_path_info_1 = require("./Timeline/find-track-for-node-
21
24
  const imperative_state_1 = require("./Timeline/imperative-state");
22
25
  const parse_keyframe_field_from_node_path_1 = require("./Timeline/parse-keyframe-field-from-node-path");
23
26
  const should_show_track_in_timeline_1 = require("./Timeline/should-show-track-in-timeline");
27
+ const timeline_refs_1 = require("./Timeline/timeline-refs");
24
28
  const TimelineSelection_1 = require("./Timeline/TimelineSelection");
25
29
  const get_stack_1 = require("./Timeline/TimelineStack/get-stack");
26
30
  const use_resolved_stack_react_to_change_1 = require("./Timeline/use-resolved-stack-react-to-change");
@@ -64,7 +68,7 @@ const WebMcp = () => {
64
68
  const { canSelect, clearSelection, selectedItems, selectItems } = (0, TimelineSelection_1.useTimelineSelection)();
65
69
  const { canvasContent, compositions, currentCompositionMetadata, folders } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
66
70
  const { playbackRate: currentPlaybackRate, setPlaybackRate } = remotion_1.Internals.usePlaybackRate();
67
- const [, , imperativePlaying] = remotion_1.Internals.Timeline.usePlayingState();
71
+ const { isPlaying } = remotion_1.Internals.Timeline.useTimelineContext();
68
72
  const { mediaVolume, playerMuted } = (0, react_1.useContext)(remotion_1.Internals.MediaVolumeContext);
69
73
  const { setPlayerMuted } = (0, react_1.useContext)(remotion_1.Internals.SetMediaVolumeContext);
70
74
  const { setZoom: setTimelineZoom, zoom: timelineZoomMap } = (0, react_1.useContext)(timeline_zoom_1.TimelineZoomCtx);
@@ -201,6 +205,62 @@ const WebMcp = () => {
201
205
  }).filter((timelineTrack) => (0, should_show_track_in_timeline_1.shouldShowTrackInTimeline)(timelineTrack, durationInFrames));
202
206
  };
203
207
  Promise.all([
208
+ modelContext.registerTool({
209
+ name: 'restart_studio',
210
+ title: 'Restart Studio',
211
+ description: 'Restart the Studio server. The browser temporarily disconnects and reconnects when Studio is ready. Only available in a writable Studio with a server backend.',
212
+ inputSchema: {
213
+ type: 'object',
214
+ properties: {},
215
+ additionalProperties: false,
216
+ },
217
+ annotations: { readOnlyHint: false },
218
+ execute: () => (0, restart_studio_1.restartStudio)(),
219
+ }, { signal: controller.signal }),
220
+ modelContext.registerTool({
221
+ name: 'shut_down_studio',
222
+ title: 'Shut down Studio',
223
+ description: 'Gracefully shut down the Studio server. The browser disconnects. Start Studio again from the terminal to reconnect. Only available in a writable Studio with a server backend.',
224
+ inputSchema: {
225
+ type: 'object',
226
+ properties: {},
227
+ additionalProperties: false,
228
+ },
229
+ annotations: { readOnlyHint: false },
230
+ execute: () => (0, shut_down_studio_1.shutDownStudio)(),
231
+ }, { signal: controller.signal }),
232
+ modelContext.registerTool({
233
+ name: 'get_current_error',
234
+ title: 'Get current Studio error',
235
+ description: 'Read the error currently shown in the Remotion Studio error overlay. Returns null when the overlay is not visible and includes symbolicated stack frames when symbolication succeeds.',
236
+ inputSchema: {
237
+ type: 'object',
238
+ properties: {},
239
+ additionalProperties: false,
240
+ },
241
+ annotations: { readOnlyHint: true },
242
+ execute: async () => {
243
+ var _a, _b;
244
+ const currentError = (0, current_error_1.getCurrentError)();
245
+ if (currentError === null) {
246
+ return null;
247
+ }
248
+ let symbolicatedStackFrames = null;
249
+ try {
250
+ const record = await currentError.symbolication;
251
+ symbolicatedStackFrames = (_a = record === null || record === void 0 ? void 0 : record.stackFrames) !== null && _a !== void 0 ? _a : null;
252
+ }
253
+ catch (_c) {
254
+ // Fall back to the original stack if symbolication fails.
255
+ }
256
+ return {
257
+ name: currentError.error.name,
258
+ message: currentError.error.message,
259
+ stack: (_b = currentError.error.stack) !== null && _b !== void 0 ? _b : null,
260
+ symbolicatedStackFrames,
261
+ };
262
+ },
263
+ }, { signal: controller.signal }),
204
264
  modelContext.registerTool({
205
265
  name: 'get_compositions',
206
266
  title: 'Get Studio compositions',
@@ -496,6 +556,7 @@ const WebMcp = () => {
496
556
  annotations: { readOnlyHint: true },
497
557
  execute: () => {
498
558
  var _a;
559
+ var _b, _c;
499
560
  const compositionId = currentCompositionRef.current;
500
561
  if (compositionId === null) {
501
562
  return Promise.resolve({
@@ -509,17 +570,28 @@ const WebMcp = () => {
509
570
  timelineZoom: null,
510
571
  });
511
572
  }
573
+ const durationInFrames = (0, imperative_state_1.getCurrentDuration)();
574
+ const timelineViewportWidth = (_b = (_a = timeline_refs_1.scrollableRef.current) === null || _a === void 0 ? void 0 : _a.clientWidth) !== null && _b !== void 0 ? _b : 0;
575
+ const minZoom = (0, get_timeline_max_zoom_1.getTimelineMinZoom)({
576
+ durationInFrames,
577
+ timelineViewportWidth,
578
+ });
579
+ const timelineZoom = (0, get_timeline_max_zoom_1.getTimelineZoom)({
580
+ durationInFrames,
581
+ timelineViewportWidth,
582
+ zoom: (_c = timelineZoomRef.current[compositionId]) !== null && _c !== void 0 ? _c : null,
583
+ });
512
584
  return Promise.resolve({
513
585
  currentComposition: compositionId,
514
586
  currentFrame: (0, imperative_state_1.getCurrentFrame)(),
515
- playing: imperativePlaying.current,
587
+ playing: isPlaying(),
516
588
  muted: playerMutedRef.current,
517
589
  volume: mediaVolumeRef.current,
518
590
  playbackRate: playbackRateRef.current,
519
591
  looping: (0, loop_1.loadLoopOption)(),
520
592
  timelineZoom: (0, get_timeline_max_zoom_1.timelineZoomToNormalized)({
521
- zoom: (_a = timelineZoomRef.current[compositionId]) !== null && _a !== void 0 ? _a : get_timeline_max_zoom_1.TIMELINE_MIN_ZOOM,
522
- maxZoom: (0, get_timeline_max_zoom_1.getTimelineMaxZoom)((0, imperative_state_1.getCurrentDuration)()),
593
+ zoom: timelineZoom,
594
+ minZoom,
523
595
  }),
524
596
  });
525
597
  },
@@ -823,6 +895,8 @@ const WebMcp = () => {
823
895
  },
824
896
  annotations: { readOnlyHint: false },
825
897
  execute: ({ zoom }) => {
898
+ var _a;
899
+ var _b;
826
900
  if (typeof zoom !== 'number' ||
827
901
  !Number.isFinite(zoom) ||
828
902
  zoom < 0 ||
@@ -837,13 +911,18 @@ const WebMcp = () => {
837
911
  if (durationInFrames <= 1) {
838
912
  throw new Error('The current composition is a still and has no timeline zoom.');
839
913
  }
840
- const maxZoom = (0, get_timeline_max_zoom_1.getTimelineMaxZoom)(durationInFrames);
914
+ const timelineViewportWidth = (_b = (_a = timeline_refs_1.scrollableRef.current) === null || _a === void 0 ? void 0 : _a.clientWidth) !== null && _b !== void 0 ? _b : 0;
915
+ const minZoom = (0, get_timeline_max_zoom_1.getTimelineMinZoom)({
916
+ durationInFrames,
917
+ timelineViewportWidth,
918
+ });
841
919
  const timelineZoom = (0, get_timeline_max_zoom_1.clampTimelineZoom)({
842
920
  zoom: (0, get_timeline_max_zoom_1.normalizedToTimelineZoom)({
843
921
  normalized: zoom,
844
- maxZoom,
922
+ minZoom,
845
923
  }),
846
924
  durationInFrames,
925
+ timelineViewportWidth,
847
926
  });
848
927
  setTimelineZoom(compositionId, () => timelineZoom, {
849
928
  anchorFrame: null,
@@ -853,7 +932,7 @@ const WebMcp = () => {
853
932
  currentComposition: compositionId,
854
933
  timelineZoom: (0, get_timeline_max_zoom_1.timelineZoomToNormalized)({
855
934
  zoom: timelineZoom,
856
- maxZoom,
935
+ minZoom,
857
936
  }),
858
937
  });
859
938
  },
@@ -931,7 +1010,7 @@ const WebMcp = () => {
931
1010
  };
932
1011
  }, [
933
1012
  clearSelection,
934
- imperativePlaying,
1013
+ isPlaying,
935
1014
  selectComposition,
936
1015
  selectItems,
937
1016
  setEditorShowGuides,
@@ -6,7 +6,7 @@ const remotion_1 = require("remotion");
6
6
  const timeline_zoom_1 = require("../state/timeline-zoom");
7
7
  const load_canvas_content_from_url_1 = require("./load-canvas-content-from-url");
8
8
  const makeKey = () => {
9
- return `remotion.zoom-map`;
9
+ return `remotion.zoom-map-pixels-per-frame`;
10
10
  };
11
11
  const persistCurrentZoom = (zoom) => {
12
12
  localStorage.setItem(makeKey(), JSON.stringify(zoom));
@@ -17,7 +17,7 @@ const getZoomFromLocalStorage = () => {
17
17
  };
18
18
  exports.getZoomFromLocalStorage = getZoomFromLocalStorage;
19
19
  const ZoomPersistor = () => {
20
- const [playing] = remotion_1.Internals.Timeline.usePlayingState();
20
+ const playing = remotion_1.Internals.usePlaying();
21
21
  const { zoom } = (0, react_1.useContext)(timeline_zoom_1.TimelineZoomCtx);
22
22
  const { canvasContent } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
23
23
  const urlState = (0, load_canvas_content_from_url_1.deriveCanvasContentFromUrl)();
@@ -0,0 +1,36 @@
1
+ import type { SymbolicatedStackFrame } from '@remotion/studio-shared';
2
+ export type CompositionDragData = {
3
+ readonly type: 'remotion-composition';
4
+ readonly version: 1;
5
+ readonly compositionId: string;
6
+ readonly compositionFile: string | null;
7
+ };
8
+ export type CompositionDragPreviewMetadata = {
9
+ readonly type: 'composition';
10
+ readonly width: number | null;
11
+ readonly height: number | null;
12
+ readonly durationInFrames: number | null;
13
+ readonly mimeType: string;
14
+ };
15
+ type MakeCompositionDragDataInput = {
16
+ readonly compositionFile: string | null;
17
+ readonly compositionId: string;
18
+ readonly width: number | null;
19
+ readonly height: number | null;
20
+ readonly durationInFrames: number | null;
21
+ };
22
+ type SerializedCompositionDragData = {
23
+ readonly mimeType: string;
24
+ readonly payload: string;
25
+ };
26
+ type CompositionDragDataTransfer = {
27
+ readonly types: ArrayLike<string>;
28
+ readonly getData: (mimeType: string) => string;
29
+ };
30
+ export declare const makeCompositionDragData: ({ compositionFile, compositionId, width, height, durationInFrames, }: MakeCompositionDragDataInput) => SerializedCompositionDragData & {
31
+ readonly data: CompositionDragData;
32
+ };
33
+ export declare const getCompositionDragPreviewMetadata: (mimeTypes: ArrayLike<string>) => CompositionDragPreviewMetadata | null;
34
+ export declare const parseCompositionDragData: (source: CompositionDragDataTransfer | SerializedCompositionDragData) => CompositionDragData | null;
35
+ export declare const compositionDragDataToSymbolicatedStack: (dragData: CompositionDragData) => SymbolicatedStackFrame | null;
36
+ export {};